moving files and folders to a subfolder
Solution 1
After more digging and experimentation. I found the answer:
-prune
is used to avoid recusing into sub-directories. ! -name
is used to exclude the target sub-directory, and then exec
executes the move operation. The {}
is replaced with file/directory names from the find
command.
find /my/path/* -prune ! -name subfolder -exec mv {} /my/path/subfolder/. +
Solution 2
mv * subfolder
Of course, it will fail moving the "subfolder" directory into itself, but everything else will move
Solution 3
Solutions that use *
(expanded by shell) won't work with too many objects in /my/path/
. In such case you'll get:
argument list too long
This approach doesn't use *
:
cd /my/path/ &&
find . -mindepth 1 -maxdepth 1 ! -name subfolder -exec mv -t subfolder/ {} +
Unfortunately -mindepth
and -maxdepth
options of find
are not POSIX-compliant; neither -t
option of mv
is, I think.
This variant should satisfy POSIX:
cd /my/path/ &&
find . ! -name . -prune ! -name subfolder -exec mv {} subfolder/ \;
(I adapted this Unix & Linux SE answer). Sadly it calls mv
for every object found, thus it's slow.
Fast alternative approach, if only you can create directories anew (initially neither /my/path/subfolder/
nor /my/subfolder/
should exist):
- rename
path/
tosubfolder/
, - recreate
path/
, - move
subfolder/
intopath/
.
Note on inode-based filesystem this should be equally fast, no matter how many objects there are in path/
. The code:
cd /my/ &&
test ! -e subfolder/ && mv path/ subfolder/ &&
mkdir path/ &&
mv subfolder/ path/
In this case I used &&
a lot to emphasize the procedure should abort if any of its steps fails. However this approach is inconvenient if you need path/
or subfolder/
to have non-default permissions, ownership etc.
Solution 4
Although i'm a bit late, I was in the same situation and came with a different solution that won't trigger anything to stdout, stderr or provide non-null exit code.
In case it can help someone:
items=(*)
mkdir subfolder
mv ${items[*]} subfolder
In case you have filenames containing spaces, you will have to add IFS=''
at the first line to properly escape them (which was my case).
Solution 5
The simplest way to do this is:
mv !(subfolder) subfolder
'!' means NOT, similar to programming languages, where mv will move all files and folders to the required subfolder with the exception of the subfolder.
Additional things like moving hidden folders and dot folders are described here: https://askubuntu.com/questions/91740/how-to-move-all-files-in-current-folder-to-subfolder
Related videos on Youtube
hebbo
Updated on September 18, 2022Comments
-
hebbo over 1 year
I would like to move all files and folder from one directory to one of its subfolders. How do I do that?
I am using BusyBox and linux.
ex:
move all files and folder in
/my/path/
to/my/path/subfolder/.
Copy, and then delete solutions are not affordable.
Thanks.
-
Xen2050 about 6 yearsA GUI file manager might be a good option, shouldn't have any surprises
-
-
hebbo about 6 yearsIs this in mv's specification? or is this hoping to be lucky? it may stop at first failure and I will end up with some of files and folder being moves but not all.
-
Gradyn Wursten about 6 years@hebbo it will not stop at first failure
-
Xen2050 about 6 years* excludes hidden files (or so testing shows me, though there's probably a setting for it somewhere)
-
Kamil Maciorowski about 6 yearsWhat
find
implementation can do this? Normally… -exec mv {} /my/path/subfolder/. +
fails because you cannot separate{}
and+
, they must be at the very end:{} +
; this is not the case with\;
. -
Razetime about 6 yearsThis may be unnecessarily complex.
-
hebbo about 6 yearsI am using busyBox
-
hebbo about 6 yearsThis did not work with the version of find I am using.
-
Matěj Kříž almost 5 yearsFiles with name starting with a dot (like .git) are excluded to. To hotfix this run
mv .* subfolder
(mv dot-start subfolder) -
Triamus over 4 yearsdidnt work for me
-
loopmode over 2 yearsThis is really useful. However,
items=(*)
ignores dot-files like .gitignore -
loopmode over 2 years(Cannot edit comment after 5 minutes) However,
(* .[!.]*)
seems to work fine for me:IFS='';items=(* .[!.]*);mkdir subfolder;mv ${items[*]} subfolder