Question

How can I move all files except one? I am looking for something like:

'mv ~/Linux/Old/!Tux.png ~/Linux/New/'

where I move old stuff to new stuff -folder except Tux.png. !-sign represents a negation. Is there some tool for the job?

Was it helpful?

Solution 2

Put the following to your .bashrc

shopt -s extglob

It extends regexes. You can then move all files except one by

mv !(fileOne) ~/path/newFolder

Exceptions in relation to other commands

Note that, in copying directories, the forward-flash cannot be used in the name as noticed in the thread Why extglob except breaking except condition?:

cp -r !(Backups.backupdb) /home/masi/Documents/

so Backups.backupdb/ is wrong here before the negation and I would not use it neither in moving directories because of the risk of using wrongly then globs with other commands and possible other exceptions.

OTHER TIPS

If you use bash and have the extglob shell option set (which is usually the case):

mv ~/Linux/Old/!(Tux.png) ~/Linux/New/

I would go with the traditional find & xargs way:

find ~/Linux/Old -maxdepth 1 -mindepth 1 -not -name Tux.png -print0 | 
    xargs -0 mv -t ~/Linux/New

-maxdepth 1 makes it not search recursively. If you only care about files, you can say -type f. -mindepth 1 makes it not include the ~/Linux/Old path itself into the result. Works with any filenames, including with those that contain embedded newlines.

One comment notes that the mv -t option is a probably GNU extension. For systems that don't have it

find ~/Linux/Old -maxdepth 1 -mindepth 1 -not -name Tux.png \
    -exec mv '{}' ~/Linux/New \;

A quick way would be to modify the tux filename so that your move command will not match.

For example:

mv Tux.png .Tux.png

mv * ~/somefolder

mv .Tux.png Tux.png

I think the easiest way to do is with backticks

mv `ls -1 ~/Linux/Old/ | grep -v Tux.png` ~/Linux/New/

Edit:

Use backslash with ls instead to prevent using it with alias, i.e. mostly ls is aliased as ls --color.

mv `\ls -1 ~/Linux/Old/ | grep -v Tux.png` ~/Linux/New/

Thanks @Arnold Roa

For bash, sth answer is correct. Here is the zsh (my shell of choice) syntax:

mv ~/Linux/Old/^Tux.png ~/Linux/New/

Requires EXTENDED_GLOB shell option to be set.

I find this to be a bit safer and easier to rely on for simple moves that exclude certain files or directories.

ls -1 | grep -v ^$EXCLUDE | xargs -I{} mv {} $TARGET

The following is not a 100% guaranteed method, and should not at all be attempted for scripting. But some times it is good enough for quick interactive shell usage. A file file glob like

[abc]*

(which will match all files with names starting with a, b or c) can be negated by inserting a "^" character first, i.e.

[^abc]*

I sometimes use this for not matching the "lost+found" directory, like for instance:

mv /mnt/usbdisk/[^l]* /home/user/stuff/.

Of course if there are other files starting with l I have to process those afterwards.

mv `find Linux/Old '!' -type d | fgrep -v Tux.png` Linux/New

The find command lists all regular files and the fgrep command filters out any Tux.png. The backticks tell mv to move the resulting file list.

ls ~/Linux/Old/ | grep -v Tux.png | xargs -i {} mv ~/Linux/New/'

How about:

mv $(echo * | sed s:Tux.png::g) ~/Linux/New/

You have to be in the folder though.

One can skip grep like this:

ls ~/Linux/Old/ -QI Tux.png | xargs -I{} mv ~/Linux/Old/{} ~/Linux/New/

How about you move everything in the folder and then just move Tux.png back?

I can't think of any shell syntax to say "everything except ..." offhand.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top