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