mv command: moving only certain extension files, not having a string in their name
I am trying to incorporate ‘mv’ command in a dockerfile.
I want to move only those files having certain extension, but not having a string in their name.
Suppose src directory has abc.txt, abcu.txt, def.xml, 1abc2.txt, mno.txt, pqr.txt and I want to move only .txt files and not having ‘abc’ in their name. So only mno.txt and pqr.txt are to be moved.
What would be the optimum way of doing it?
With extended shell globbing:
$ ls *.txt
1abc2.txt abc.txt abcu.txt mno.txt pqr.txt
$
# Enable extended shell globbing
$ shopt -s extglob
$
# "echo" is for a dry-run
$ echo mv -nv -t /path/to/dest -- !(*abc*).txt
mv -nv -t /path/to/dest -- mno.txt pqr.txt
$
# Disable extended shell globbing
$ shopt -u extglob
With find
:
$ find ! -name "*abc*" -name "*.txt" -exec echo mv -nv -t /path/to/dest -- {} +
mv -nv -t /path/to/dest -- ./mno.txt ./pqr.txt
Notices:
echo
is added in front ofmv
in the above two examples for a safe dry-run … You need to remove it when satisfied with the output so the actual moving will happen.- The
-t
option ofmv
specifies the target/destination directory and it expects an argument after it in the form of a path like-t /path/to/dest
. - If you need to specify the path to the source directory containing the files in the first example, then it needs to be after
--
and directly before the glob pattern likemv -nv -t /path/to/dest -- /path/to/source/!(*abc*).txt
… While in the second example, it can be done like thisfind /path/to/source/ ! -name "*abc*" -name "*.txt" -exec echo mv -nv -t /path/to/dest -- {} +
. - The first example with shell globbing after the
mv
command is subject to system’s maximum arguments length/size allowed for a command and while that should be fairly large on Ubuntu (Last I checked, it was around 2 MB) but you need to know that anyway … The second example withfind
, however, is not affected by this restriction.