Moving files with find + xargs: target is not a directory?

21,036

Solution 1

Assuming you have GNU (find, xargs, & mv), change your command to this:

$ find /foot/bar/ -name '*.csv' -print0 | xargs -0 mv -t some_dir

excerpt from mv man page

   -t, --target-directory=DIRECTORY
          move all SOURCE arguments into DIRECTORY

The above xargs ... will construct the command so that calls to move will be like this:

 $ mv 1.csv 2.csv 3.csv ... -t some_dir

Don't need xargs

You can skip this approach by just having find do all the work itself:

$ find /foot/bar/ -name '*.csv' -exec mv -t some_dir {} +

Why do you need the mv -t ...?

This has to do with the way that xargs is constructing the set of files to pass to the command it's going to run each time, (i.e. mv ...).

When you run the mv command manually yourself you control how many filenames are passed to it and so you don't need to worry about needing the -t my_dir since you always will put the destination directory last.

References

Solution 2

You can also use the ls command instead of find command:

ls /foot/bar/*.csv | xargs  mv -t some_dir
Share:
21,036

Related videos on Youtube

Amelio Vazquez-Reina
Author by

Amelio Vazquez-Reina

I'm passionate about people, technology and research. Some of my favorite quotes: "Far better an approximate answer to the right question than an exact answer to the wrong question" -- J. Tukey, 1962. "Your title makes you a manager, your people make you a leader" -- Donna Dubinsky, quoted in "Trillion Dollar Coach", 2019.

Updated on September 18, 2022

Comments

  • Amelio Vazquez-Reina
    Amelio Vazquez-Reina over 1 year

    When I run the following command:

    > mkdir some_dir
    > find /foo/bar/ -name '*.csv' -print0 | xargs -0 mv {} some_dir
    

    I get hundreds of lines that say:

    mv: target `/foo/bar/XX.csv` is not a directory
    

    Why? I thought xargs would execute:

    mv /foo/barXX.csv some_dir
    

    for every file that find finds. What's going on? By the way, this is with zsh

    Update:

    Update1:

    I tried:

    find /foo/bar/ -name '*.csv' -print0 | xargs -0 mv {} -t some_dir
    

    but then I got a few lines like:

    mv: cannot stat `{}': No such file or directory
    

    although I think the command is moving my files correctly.

    Update2:

    I don't seem to need the -t option when using mv alone. For example

    > touch file1.txt
    > touch file2.txt
    > mkdir my_dir
    > mv  file1.txt  file2.txt  my_dir
    

    works well. Why do I need -t when using xargs?

  • Amelio Vazquez-Reina
    Amelio Vazquez-Reina almost 11 years
    Thanks! This is very helpful. I am a bit confused though (see my Updates)
  • frostschutz
    frostschutz almost 11 years
    The constructed command is mv -t some_dir 1.csv 2.csv 3.csv ... so the file arguments are last. That's the error in the question, in order to use {} you have to pass -I {} to xargs.
  • slm
    slm almost 11 years
    @user815423426 - I'll update it later when I get a chance tonight, I do know why.
  • slm
    slm almost 11 years
    @user815423426 - I updated the question, let me know if it makes sense wrt mv -t.