We have a folder with more than a million files that needs sorting, but we can’t really do anything because mv outputs this message all the time
we using this command to move extension-less files:
- xargs is the tool for the job. That, or find with -exec … {} +. These tools run a command several times, with as many arguments as can be passed in one go.
- Both methods are easier to carry out when the variable argument list is at the end, which isn’t the case here: the final argument to mv is the destination.
- With GNU utilities (i.e. on non-embedded Linux or Cygwin), the -t option to mv is useful, to pass the destination first.
- If the file names have no whitespace nor any of \”‘, then you can simply provide the file names as input to xargs (the echo command is a bash built in, so it isn’t subject to the command line length limit):
- You can use the -0 option to xargs to use null-delimited input instead of the default quoted format.
- Alternatively, you can generate the list of file names with find. To avoid recursing into subdirectories, use -type d -prune. Since no action is specified for the listed image files, only the other files are moved.
- If you don’t have GNU utilities, you can use an intermediate shell to get the arguments in the right order. This method works on all POSIX systems.
- In zsh, you can load the mv builtin:
or if you prefer to let mv and other names keep referring to the external commands:
or with ksh-style globs:
Alternatively, using GNU mv and zargs:
- The operating system’s argument passing limit does not apply to expansions which happen within the shell interpreter.
- So in addition to using xargs or find, we can simply use a shell loop to break up the processing into individual mv commands:
- This uses only POSIX Shell Command Language features and utilities. This one-liner is clearer with indentation, with unnecessary semicolons removed:
- A solution without a catch block using “$origin”/!(*.jpg|*.png|*.bmp):
- For a multi-line script you can do the following (notice the ; before the done is dropped):
- To do a more generalized solution that moves all files, you can do the one-liner:
Which looks like this if you do indentation:
- This takes every file in the origin and moves them one by one to the destination. The quotes around $file are necessary in case there are spaces or other special characters in the filenames.
- Here is an example of this method that worked perfectly