0

I wanted to recursively move files from a folder (Pictures) to another (Picturesnew).

The "Pictures" Folder had many subfolders and and hence I used this command after following up the posts here.

Both Pictures and Picturesnew were in the same directory. I just wanted to get rid of all the subfolders and combine the data.

I ran the following command from the directory these folders were situated in.

find ./Pictures -type f -name "*.jpg" -print0 | 
xargs -0 -Imysongs mv -i mysongs ./Picturesnew

Now seemingly the Picturesnew folder which should have appeared didn't appear at all and hence I am confused as to where 20000 JPG files of mine went.

8
  • Why didn't you just find ./Pictures -type f -name "*.jpg" -exec mv {} Picturesnew/ \;? Mar 5, 2019 at 1:51
  • This would mean just one file left as ./Picturesnew would be treated as a target file name. But mv -i should be interactive. Were you asked 20000 times if you want to overwrite?
    – user147505
    Mar 5, 2019 at 2:13
  • (1) The command that you posted has three " characters.  Therefore, it should not have executed at all.  (2) I believe that mkdir Picturesnew  &&  mv Pictures/* Picturesnew would work (would have worked), assuming that you don't have any . files in Pictures. Mar 5, 2019 at 3:02
  • @G-Man the last " was for highlighting purposes. Edited. It did execute but it didnt work. Like Tomasz said, i created a single file with the Name Picturesnew. I am trying to locate the files which shd have been moved. Mar 5, 2019 at 14:22
  • @Tomasz where should've mv -i got its confirmation from? The stdin is the output from find. The OP should immediately remount that partition read-only and look for forensic tools if they want to recuperate their files, though that's pretty hopeless.
    – user313992
    Mar 5, 2019 at 14:37

4 Answers 4

1

You really wanted

mkdir Picturesnew
find Pictures -type f -iname "*.jpg" -exec mv -i {} + Picturesnew/

mv does not make directories.

The -i option to mv causes it to not work when run in a pipeline like that. (Though, on the bright side, it hopefully told mv to not stomp all over the first file renamed to be Picturesnew instead of whatever it was originally.)

In my solution, I'm telling find to move multiple files per instance of mv executed if useful, to minimize the chance that a mistake such as leaving the trailing / off of the target directory name and not having made the target directory would actually rename a file, rather than generating the error desired. It also has the advantage of allowing mv to actually prompt for confirmation for overwriting a file rather than simply taking the next filename as "no".

2
  • Thank you for explaining. Yes exactly like you, Tomasz and php_beggar pointed out, mv -i didnt work interactively owing to the fact that is was getting ist Input from another command(find) and the Absence of a trailing / made the mv overwrite the same file 20000 times and in the end i was left with the JPG file that was moved at last. Mar 5, 2019 at 14:59
  • @GauravGarg just wondering if you had any backup of the files or did you lost the image files ?
    – Atul
    Mar 5, 2019 at 16:33
1

I don't know how come there was no confirmation while overwriting, which should be present due to the -i parameter to mv. But assuming you didn't use it and given there was a jpg file Picturesnew after the operation, as you state in the comment under your question, well - you overwrote the same file 20000 times.

xargs -0 -Imysongs mv -i mysongs ./Picturesnew

This means for each argument this command will be executed:

mv -i argument ./Picutesnew

Since there was no directory ./Picturesnew the command mv thought you mean it should move the file here and rename to ./Picturesnew. It did so 20000 times.

After the pipeline has finished executing, there should be just one file ./Picturesnew left. The last one that was moved. The previous ones are gone.

This form is therefore much safer:

mv -i argument ./Picturesnew/

That's because the / at the end eliminates confusion as to what Picturesnew is supposed to be.

As for -i, you wouldn't put it in this pipeline, as it wouldn't work. It demands confirmation.

2
  • Thank you for explaining so precisely. I think i get it now. Like php_beggar said above, mv -i didn't work interactively as input redirection was used. Does this mean we cannot really use mv -i when clubbed along with another command where it is getting it's Input from ? Last question though. Would the file recovery Tools be of any good here.? Mar 5, 2019 at 14:55
  • @GauravGarg You can try. Maybe you have backups...
    – user147505
    Mar 5, 2019 at 14:59
0

I think you can achieve your goal with following command:

find Pictures -type f -print0 | xargs -0 mv -t Picturesnew

where Pictures is source directory and Picturesnew is destination directory.

Both mv (and cp) have format mv -t directory source... which fits good in use with xargs.

But this method will leave files with duplicate names in their original positions (maybe that's not bad since you can review them and copy to the desitnation later), since mv -t won't work interactively when input redirection is used. That is because xargs already reads values from redirected standard input (which is output of find), and mv, which is ran by xargs, tries to read answers from the same standard input too. So you cannot use mv with pipes in interactive fashion.

Maybe job can be solved by some clever input-handle reassigning, but let's try more simple way: get rid of output redirection. Also we cannot use -print0 in command substitution because it doesn't allow 0-bytes. We need to iterate over filenames with for, using newline as input-field separator:

TMP=$IFS; 
IFS=$'\n'; 
for i in $(find Pictures -type f); do 
    mv -it ../Picturesnew $i; 
done; 
IFS=$TMP

(you may copy it as a one-liner).

In this case, mv will not only ask you for each duplicate, but wait for answer as well.

0
find Pictures -type f -iname "*.jpg" -print0 | xargs -0 -I {} mv -n "{}" Picturesnew/

Would be a more syntactically correct solution, so restore your backup and try that.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .