Go to the toplevel directory of the tree containing the zip files (cd …
), then run
mv **/*.zip /path/to/single/target/directory/
This works out of the box in zsh. If your shell is bash, you'll need to run shopt -s globstar
first (you can and should put this command in your ~/.bashrc
). If your shell is ksh, you'll need to run set -o globstar
first (put it in your ~/.kshrc
).
Alternatively, use find
, which works everywhere with no special preparation but is more complicated:
find . -name '*.zip' -exec mv {} /path/to/single/target/directory/ \;
If you want to remove empty directories afterwards, in zsh:
rmdir **/*(/^Fod)
In bash or ksh:
rmdir **/*/
and repeat as long as there are empty directories to remove. Alternatively, in any shell
find . -depth -type d -empty -exec rmdir {} \;
Never, ever use for foo in $(cat bar)
. This is a classic mistake, commonly known as bash pitfall number 1. You should instead use:
while IFS= read -r file; do mv -- "$file" "new_place/$file"; done < file_list.txt
When you run the for
loop, bash will apply wordsplitting to what it reads, meaning that a strange blue cloud
will be read as a
, strange
, blue
and cloud
:
$ cat files
a strange blue cloud.txt
$ for file in $(cat files); do echo "$file"; done
a
strange
blue
cloud.txt
Compare to:
$ while IFS= read -r file; do echo "$file"; done < files
a strange blue cloud.txt
Or even, if you insist on the UUoC:
$ cat files | while IFS= read -r file; do echo "$file"; done
a strange blue cloud.txt
So, the while
loop will read over its input and use the read
to assign each line to a variable. The IFS=
sets the input field separator to NULL*, and the -r
option of read
stops it from interpreting backslash escapes (so that \t
is treated as slash + t
and not as a tab). The --
after the mv
means "treat everything after the -- as an argument and not an option", which lets you deal with file names starting with -
correctly.
* This isn't necessary here, strictly speaking, the only benefit in this scenario is that keeps read
from removing any leading or trailing whitespace, but it is a good habit to get into for when you need to deal with filenames containing newline characters, or in general, when you need to be able to deal with arbitrary file names.
Best Answer
This would move all files with
.txt
and.txt.exe
extensions present anywhere inside the current directory (even in subdirectories) to~/Desktop/tmpremo
.If you want another extension too, just add
-o -iname '*.extension'
before the-exec
.PS: As @xenoid noted, please refrain from using
sudo
unless it is absolutely required for the task at hand.