Quantcast
Channel: Find and move with exclude - Unix & Linux Stack Exchange
Viewing all articles
Browse latest Browse all 5

Answer by Gilles for Find and move with exclude

$
0
0

It's generally a bad idea to parse the output of ls or find, because you can't distinguish which characters are part of a file name and which characters are separators. If you don't control the file names, this can be a security hole, allowing an adversary to craft file names that cause your script to execute arbitrary code. See Why does my shell script choke on whitespace or other special characters?. It may be ok in your case though, especially as your files seem to be some kind of source code tree where it's common to have file names with no “exotic” characters, in particular no spaces.

Still, it isn't really more difficult to use a robust command. The core idea is to make find invoke mv instead of parsing the output of find. The following command moves .xml from the current directory and subdirectories recursively:

find . ! -type d -name '*.xml' ! -name deposit.xml -exec mv {} ./Archive \;

To speed this up a little, you can group invocations of mv by running an intermediate shell.

find . ! -type d -name '*.xml' ! -name deposit.xml -exec sh -c 'mv "$@" "$0"' ./Archive {} +

If you meant to move only files from the current directory, without traversing subdirectories, then you need to instruct find not to recurse. If your find implementation supports the -maxdepth option:

find . -maxdepth 1 ! -type d -name '*.xml' ! -name deposit.xml -exec sh -c 'mv "$@" "$0"' ./Archive {} +

Otherwise:

find . -name . -o -type d -prune -o -name '*.xml' ! -name deposit.xml -exec sh -c 'mv "$@" "$0"' ./Archive {} +

If your shell is ksh, you can use its extended globs. This is easier than using find, but less portable. To move files in the current directory:

mv !(deposit).xml Archive/

In ksh93, to move files from subdirectories as well:

set -o globstar
mv **/!(deposit).xml Archive/

In bash, you can use the !(…) pattern as well, but you need to run shopt -s extglob first. To use the **/ pattern, you need to run shopt -s globstar first, and beware that up to bash 4.2, **/ traverses symbolic links to directories in addition to directories.

shopt -s extglob globstar
mv **/!(deposit).xml Archive/

In zsh, you can use the !(…) pattern after running setopt ksh_glob. Alternatively, you can use zsh's syntax for that after running setopt extended_glob. The recursive traversal syntax is available either way.

setopt extglob
mv **/(^deposit).xml Archive/

Viewing all articles
Browse latest Browse all 5

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>