1

I am trying to move my files from current dir to another dir. The issue I am having is that multiple files have a name with special characters like space, ü, &, (, .... How can I move all my files using a command like: ls | grep mp4 | xargs -i mv {} mp4, where {} is supposed to be the name of the current file and mp4 the destination put all my file. I have tried the command but it shows errors. Can you please help ?

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
dmx
  • 111
  • 1
    Can you show us the errors, telepathy mode is currently off line. – ctrl-alt-delor Apr 14 '17 at 22:06
  • @richard This is the error xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option – dmx Apr 15 '17 at 04:33
  • @dmx, the man page for GNU xargs states that "xargs reads items from the standard input, delimited by blanks (which can be protected with double or single quotes or a backslash) or newlines" so quotes are indeed special. Try e.g. echo "'foo bar' doo\ goo" | xargs -n1 echo. – ilkkachu Apr 15 '17 at 09:49
  • @dmx, see the xargs-specific part here – ilkkachu Apr 15 '17 at 09:50

2 Answers2

5

This is exactly the situation you don't want to use ls in. Or xargs with default settings, it will split the input on spaces, and handles quotes and backslashes specially. You'd need to use -0 to separate input on null bytes, or -d'\n' to separate on newlines (GNU xargs) to turn that behaviour off.

As all the files are in the same directory, you can just use the shell:

mv *mp4* mp4/

Or mv *.mp4 mp4/ if you only meant files files that have mp4 as an extension. The first one would warn about moving mp4 itself to mp4.)


If the files were not in the same directory, you'd need to either use the double-star (zsh - enabled by default or ksh with set -o globstar or bash with shopt -s globstar):

mv **/*mp4* mp4/

or find

find . -type f -name "*mp*" -exec mv {} mp4/ \;
ilkkachu
  • 138,973
4

The command:

ls | grep mp4 | xargs -i mv {} mp4

can in most cases be replaced by the simpler and more robust:

mv *mp4* mp4

You can ignore the warning about the directory mp4 not being movable inside itself.

Note that this script, like yours, is moving all files having "mp4" appearing anywhere in their name (e.g.: mp4list.txt, lamp4.jpg). Should you actually want to only move files with the extension ".mp4", you can use:

mv *.mp4 mp4

That would prevent the situation leading to the error message about the directory mp4 itself to occur.

Should the number of mp4 files is huge and prevent the former command to work, you might use GNU find to achieve the same:

find . -maxdepth 1 -name "*mp4*" -exec mv -t mp4 {} +

or

find . -maxdepth 1 -name "*.mp4" -exec mv -t mp4 {} +
jlliagre
  • 61,204