I'm using bash on Mac 10.9.5. I have PDF files in many directories, all one level from the root ...


How do I write a shell command to move all these files into the "root" directory, that is make the files line up alongside the child directories ...




How about just:

mv ./*/*.pdf .

I've done a test on my computer (zsh 5.0.7 (x86_64-pc-linux-gnu)) and it worked perfectly:

> ls -r *    

r.2  r.1

s.2  s.1

t.2  t.1

> mv ./*/*.pdf .
> ls
r.1  r.2  s.1  s.2  sub1  sub2  sub3  t.1  t.2

> tree                                                            
├── r.1
├── r.2
├── s.1
├── s.2
├── sub1
├── sub2
├── sub3
├── t.1
└── t.2
  • This is what I had intended to write, but did not have enough indenting so the * got eaten. – wurtel Mar 20 '15 at 14:58

You could use find for this:

find * -name "*.pdf" -maxdepth 1 -type f -exec mv {} ../ \;
  • -name "*.pdf" means the pattern to match
  • -maxdepth 1 means it will only go one level deep
  • -type f means ignore everything that's not a file (includes symlinks, directories etc.)
  • -exec mv {} ../ \; is the command to execute for each file found - to be specific, this means the command is mv <FILENAME> ../
  • Hi, When I enter your command, I get a "find: *.pdf: No such file or directory" error, even though there are definitely files in those directories with ".pdf" extensions. – Dave Mar 20 '15 at 13:34
  • I apologize, I didn't test it so there was an error I missed, the pattern needs to be * while .pdf files are matched using -name - edited it now. – fstanis Mar 20 '15 at 13:54
  • You should use . as begin point for find instead of *. If there are very many files in the current directory this will also fail with argument list too long. – wurtel Mar 20 '15 at 14:55
  • What is the difference between using * and . in this case? – fstanis Mar 20 '15 at 15:46
mv */*.PDF .

That will expand to a list of all files with extension .PDF in all subdirectories one level deep, and move those to the current directory.

A complication may arise if there are so many that you get the error argument list too long. In that case this will work, assuming there are no special characters like spaces, semicolons, quotes etc. in the directory or file names:

echo */*.PDF | xargs -i{} mv {} .

xargs is made for such situations: it takes strings on its input, collects as many as will go in a single execution, and then run the command given with the collected list. Here we tell xargs to replace {} with the list.

  • Hi, When I enter the echo command, I get a "xargs: illegal option -- i" error. Note that I'm using bash on Mac 10.9.5 if that matters. – Dave Mar 20 '15 at 13:35
  • To best of my knowledge I think mv /.PDF . will search in root directory / for hidden file (because of .) that is named .PDF. But, maybe I'm wrong. I have never seen such syntax for mv. – mnmnc Mar 20 '15 at 14:02
  • The mv /.PDF . happened because the formatting ate my * characters. I'll edit it now. Sorry about that. – wurtel Mar 20 '15 at 14:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.