7

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.

1
  • A GUI file manager might be a good option, shouldn't have any surprises
    – Xen2050
    Commented Apr 12, 2018 at 0:49

6 Answers 6

12
mv * subfolder 

Of course, it will fail moving the "subfolder" directory into itself, but everything else will move

5
  • 2
    Is 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. Commented Apr 11, 2018 at 23:18
  • 1
    @hebbo it will not stop at first failure Commented Apr 12, 2018 at 0:29
  • * excludes hidden files (or so testing shows me, though there's probably a setting for it somewhere)
    – Xen2050
    Commented Apr 12, 2018 at 0:48
  • Files with name starting with a dot (like .git) are excluded to. To hotfix this run mv .* subfolder (mv dot-start subfolder) Commented Aug 6, 2019 at 12:14
  • didnt work for me
    – Triamus
    Commented Oct 23, 2019 at 14:45
2

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/ to subfolder/,
  • recreate path/,
  • move subfolder/ into path/.

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.

2

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

2
  • 1
    This did not work with the version of find I am using. Commented Apr 12, 2018 at 15:52
  • This has nothing with find to do. It uses the mv command but more crucially the shell's wildcard feature. You have to enable shopt -s extglob in many versions on Bash to get access to this "extended globbing" wildcard syntax.
    – tripleee
    Commented Apr 26, 2023 at 4:56
1

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).

3
  • This is really useful. However, items=(*) ignores dot-files like .gitignore
    – loopmode
    Commented Nov 4, 2021 at 14:26
  • (Cannot edit comment after 5 minutes) However, (* .[!.]*) seems to work fine for me: IFS='';items=(* .[!.]*);mkdir subfolder;mv ${items[*]} subfolder
    – loopmode
    Commented Nov 4, 2021 at 14:52
  • This will fail on file names with spaces or newlines etc in their names. You want mv "${items[@]}" subfolder
    – tripleee
    Commented Apr 26, 2023 at 4:58
0

You might want to check out the mv command. You can try searching for all files and folders in a directory and exclude a sub-directory then copy all found to that sub-directory using find with the mv command.

See a similar stack-overflow question https://stackoverflow.com/questions/4612157/how-to-use-mv-command-to-move-files-except-those-in-a-specific-directory

0

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/. +
3
  • What 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 \;. Commented Apr 12, 2018 at 4:57
  • This may be unnecessarily complex.
    – Razetime
    Commented Apr 12, 2018 at 5:04
  • I am using busyBox Commented Apr 12, 2018 at 15:49

You must log in to answer this question.

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