I have a bunch of .zip files in several directories:
Fol1/Fol2
Fol3
Fol4/Fol5
How would I do move them all to a common base folder?
I have a bunch of .zip files in several directories:
Fol1/Fol2
Fol3
Fol4/Fol5
How would I do move them all to a common base folder?
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 {} \;
find
command above worked in bash, but had to change to find . -name
etc to get it to work.
Commented
May 29, 2017 at 19:08
.
is implicit for GNU find but not for others, I've added it explicitly.
Commented
May 29, 2017 at 20:31
directory
doesn't exist in /path/to/single/target/
, the mv
command will rename each file to directory
and each one will overwrite the last, essentially deleting all your files.
directory/
which causes an error if the directory doesn't exist or if it's a regular file.
Commented
Mar 10, 2020 at 13:50
If you only want to move the .zip
files, you could do something like
mkdir ./zipfiles
find . -name "*.zip" -exec mv "{}" ./zipfiles \;
find . type f -exec mv "{}" dest-dir \;
find . -path "./zipfiles" -prune -o -name "*.zip" -exec mv "{}" ./zipfiles \;
would avoid this, imo.
Commented
Jan 29 at 5:11
This one is safe when moving data and error free which supported most of all distro regardless versions. This command will scan subdirectories and then move or copy to your new destination directory.
find . -name *.flac -exec mv '{}' "./flac/" ";"
*.flac
to anything like *.zip
in your case. Or *.doc
just any extension works.mv
is the command to move files, or you can use cp
to copy data instead of moving. ./flac/
is the destination directory that I want to move all FLAC files to. You can also give it a full path like /home/myid/flac/
Full example. (in this case, there are many subdirectories with music artist name at /home/myid/Music/
and then FLAC files are all over different subdirectories level.
Since I don't need artist folders but want to have all FLAC files into one directory at /home/myid/Music/flac/
cd /home/myid/Music
mkdir flac
find . -name *.flac -exec mv '{}' "./flac/" ";"
cd flac
ls
Then it will display all FLAC files.
If you're using bash version 4 or higher or zsh you can also use recursive globbing:
mv **/*.zip /path/to/move/zip/files/to
This will move ONLY the files and not their relative paths, so collisions might occur.
Assuming you have the GNU versions of find and mv, the following will be more efficient than the existing find-based answers:
find . -name '*.zip' -exec mv --target-directory='/path/to/outputdir' '{}' +
Using a +
at the end of the find -exec means that a list of files will be passed to the mv command, rather than executing one mv command per file found. However, a limitation of this is that you can only place the '{}' at the end of the command, which necessitates the use of the mv --target-directory option, and as far as I know that's a GNU-ism.
As a bash hack, you could use the power of tar
:
(cd origin/;find . -exec file --mime-type "{}" \;|grep "application/zip"|cut -d ':' -f 1|xargs tar cf -)|(cd target/; tar xf -) && rm -fr origin/
This has the advantage that it does not depend on file extensions, since it uses the file
command to choose the files to move and it preserves the directory structure, but it doesn't work with paths containing spaces.
The final rm
is there just to remove the original files (becouse @InquilineKea tolds that he doesn't care about the original folder in the comment).
Of course this is particularly suitable if the origin/ and target/ folders are on different disks. Otherwise the other solutions proposed are more efficient (even if they rely on naming conventions, instead of file
's content).
In addition to Gilles' advice where he suggested
mv **/*.zip /path/to/single/target/directory/
you may get feedback saying
mv: will not overwrite just-created
because there might be duplicate file names being copied to the target directory.
If you add --backup=numbered
this will create numbered backup files with duplicate names.
e.g. duplicate-name.zip.~1~