How do I find all files in a folder and its subfolders terminated with 3 digits and move them to a new place while keeping the directory structure?
Alternatively, how can I find all files whose names don't end with three digits?
How do I find all files in a folder and its subfolders terminated with 3 digits and move them to a new place while keeping the directory structure?
Alternatively, how can I find all files whose names don't end with three digits?
Much cleaner solution, based on an answer linked by @don_crissti. (Rsync filter: copying one pattern only)
rsync -av --remove-source-files --include='*[0-9][0-9][0-9]' --include='*/' --exclude '*' /tmp/oldstruct/ /tmp/newstruct/
And the negation:
rsync -av --remove-source-files --exclude='*[0-9][0-9][0-9]' /tmp/oldstruct /tmp/newstruct/
Original answer:
This should do it. It will find any file in the structure you cd into ending in 3 digits, create a destination folder in the /tmp/newstruct, and move the file.
cd /tmp/oldstruct
find ./ -type f -regextype posix-basic -regex '.*[0-9]\\{3\\}' |
while read i; do
dest=/tmp/newstruct/$(dirname $i)
mkdir -vp $dest
mv -v $i $dest
done
I'd recommend prepending the mkdir and mv with echo before you actually run it, just to ensure it does what you're expecting.
To negate the 3 digits, simply place do ! -regex instead.
Here is a simpler method which relies upon rsync. However, it does call rsync for every file it finds, so definitely not very efficient.
find ./ -type f -regextype posix-basic -regex '.*[0-9]\{3\}' --exec rsync -av --remove-source-files --relative {} /tmp/newstruct
You can do this with bash :
## Make ** match all files and 0 or more dirs and subdirs
shopt globstar
## Iterate over all files and directories
for f in **; do
## Get the name of the parent directory of the
## current file/directory
dir=$(dirname "$f");
## If this file/dir ends with 3 digits and is a file
if [[ $f =~ [0-9]{3} ]] && [ -f "$f" ]; then
## Create the target directory
mkdir -p targetdir1/"$dir"
## Move the file
mv "$f" targetdir1/"$f"
else
## If this is a file but doesn't end with 3 digits
[ -f "$f" ] &&
## Make the target dir
mkdir -p targetdir2/"$dir" &&
## Move the file
mv "$f" targetdir2/"$f"
fi
done