I am wondering - how can I move all the files in a directory except those files in a specific directory (as 'mv' does not have a '--exclude' option)?
12 Answers
Lets's assume the dir structure is like,
|parent
    |--child1
    |--child2
    |--grandChild1
    |--grandChild2
    |--grandChild3
    |--grandChild4
    |--grandChild5
    |--grandChild6
And we need to move files so that it would appear like,
|parent
    |--child1
    |   |--grandChild1
    |   |--grandChild2
    |   |--grandChild3
    |   |--grandChild4
    |   |--grandChild5
    |   |--grandChild6
    |--child2
In this case, you need to exclude two directories child1 and child2, and move rest of the directories in to child1 directory.
use,
mv !(child1|child2) child1
This will move all of rest of the directories into child1 directory.
 
    
    - 2,640
- 5
- 23
- 23
- 
                    26Tip: Note however that using this pattern relies on `extglob`. You can enable it using `shopt -s extglob` (If you want `extended globs` to be turned on by default you can add `shopt -s extglob` to .bashrc) – Boris D. Teoharov Aug 20 '14 at 19:03
- 
                    19I keep getting `-bash: !: event not found` when trying to do this command. – FilBot3 Dec 04 '14 at 01:10
- 
                    3
- 
                    1How can this be forced? when there are no other directories other than the ones ignored? ```mv -f``` does not seem to work. I've temp solved it by creating a temp directory so there are three dirs in total, then moving all directories, then removing the temp dir. ugly! – Michahell Apr 07 '15 at 14:21
- 
                    Be careful with this one that you really want *everything* in that directory in that other directory! – Noumenon Aug 31 '16 at 15:46
- 
                    Thank you for providing an easy to understand example, I really appreciate it! – Terren Jun 13 '18 at 23:51
- 
                    If needed, `shopt -u extglob` to toggle "off" (view status with `shopt extglob`). – Victoria Stuart Jun 15 '19 at 18:07
- 
                    Note that this **will not work if** you write e.g. `mv !(child1/) grandChild*` - the name of the directory to exclude must not contain the trailing slash! – Jo Mo Feb 15 '21 at 06:35
Since find does have an exclude option, use find + xargs + mv:
find /source/directory -name ignore-directory-name -prune -print0 | xargs -0 mv --target-directory=/target/directory
Note that this is almost copied from the find man page (I think using mv --target-directory is better than cpio).
 
    
    - 1,694
- 9
- 8
First get the names of files and folders and exclude whichever you want:
ls --ignore=file1 --ignore==folder1 --ignore==regular-expression1 ...
Then pass filtered names to mv as the first parameter and the second parameter will be the destination:
mv $(ls --ignore=file1 --ignore==folder1 --ignore==regular-expression1 ...) destination/
This isn't exactly what you asked for, but it might do the job:
mv the-folder-you-want-to-exclude somewhere-outside-of-the-main-tree
mv the-tree where-you-want-it
mv the-excluded-folder original-location
(Essentially, move the excluded folder out of the larger tree to be moved.)
So, if I have a/ and I want to exclude a/b/c/*:
mv a/b/c ../c
mv a final_destination
mkdir -p a/b
mv ../c a/b/c
Or something like that. Otherwise, you might be able to get find to help you.
 
    
    - 42,585
- 14
- 91
- 146
- 
                    And if the files you are moving are in your root? Some systems, for instance, only give user access to one directory (some cloud IDEs are a good example). Maybe someone wants to move everything to a child directory. This won't work. – Kallaste Sep 25 '17 at 18:00
- 
                    1As I said (six years ago), the answer doesn't describe exactly what was asked for, and it only *might* do the job. For most cases, it should work; certainly, yours is an exception to that. – Thanatos Sep 25 '17 at 23:00
- 
                    You're right, it does not. But my point was not that it wasn't what was asked for, but that it in some cases would not work. My example was just a hypothetical to demonstrate that. – Kallaste Sep 26 '17 at 04:27
rename your directory to make it hidden so the wildcard does not see it:
mv specific_dir .specific_dir 
mv * ../other_dir
 
    
    - 355
- 3
- 6
This will move all files at or below the current directory not in the ./exclude/ directory to /wherever...
find -E . -not -type d -and -not -regex '\./exclude/.*' -exec echo mv {} /wherever \;
 
    
    - 9,769
- 1
- 25
- 36
- 
                    this will ignore directory structure and copy all files in sub directories into one flat folder structure. a/b/c/ -> /wherever a/b.txt -> /wherever – Govinnage Rasika Perera Jul 02 '15 at 05:04
- 
                    
ls | grep -v exclude-dir | xargs -t -I '{}' mv {} exclude-dir
 
    
    - 5,031
- 17
- 33
- 41
 
    
    - 100
- 1
- 4
- 
                    8Would you like to add some explanation to your code-only answer? It would help fighting the misconception that StackOverflow is a free code writing service. Also, have a look here to improve appearance: https://stackoverflow.com/editing-help – Yunnosch May 20 '19 at 06:18
#!/bin/bash
touch apple  banana  carrot  dog  cherry
mkdir fruit
F="apple  banana  carrot  dog cherry"
mv ${F/dog/} fruit
# this removes 'dog' from the list F, so it remains in the current directory and not moved to 'fruit'
 
    
    - 460
- 4
- 9
Inspired by @user13747357 's answer.
First you can ls the file and filter them by:
ls | egrep -v '(dir_name|file_name.ext)'
Then you can run the following command to move the files except the specific ones:
mv $(ls | egrep -v '(dir_name|file_name.ext)') target_dir
* Note that I tested this inside a specific directory. Cross-directory operation should be more carefully executed :)
 
    
    - 33
- 4
suppose you directory is
.
├── dir1
│    └── a.txt
├── dir2
│    ├── b.txt
│    └── hello.c
├── file1.txt
├── file2.txt
└── file3.txt
and you gonna put file1 file2 file3 into dir2.
you can use
mv $(ls -p | grep -v /)  /dir2 to finish it, because
ls -p | grep -v / will print all files except directory in cwd.
 
    
    - 29
- 6
For example, if I want to move all files/directories - except a specified file or directory - inside "var/www/html" to a sub-folder named "my_sub_domain", then I use "mv" with the command "!(what_to_exclude)":
$ cd /var/www/html $ mv !(my_sub_domain) my_sub_domain
To exclude more I use "|" to seperate file/directory names:
$ mv !(my_sub_domain|test1.html) my_sub_domain
 
    
    - 90
- 11
 
     
    