Update: Added a version which can handle any/all valid filename characters, except for \x01
, which is used as sed's delimiter.... I have used A.*
as the pattern in the updated examples, because I was testing for A"'
. Of course, just change to whatever you need.
findx="\(.*/\)\(A.* \)\([0-9]\)$"
replx="&\x00\1\20\3\x00"; I=$'\x01'
find . -depth -type d -regex "$findx" |
sed -n "s$I$findx$I$replx$I p" |
tr -d '\n' |
xargs --verbose -0n2 mv
Here is an example, using perl
instead of sed
.
Note that perl's regualar expressions PCRE
are not entirely the same as posix-extended ERE
as used by find
in this example. They do, however, share enough in common that the same regex pattern can be used in this case.
export findx='(.*/)(A.* )([0-9])$'
find . -depth -type d -regextype posix-extended -regex "$findx" |
perl -l000pe 's/$ENV{'findx'}/$_\000$1${2}0$3/' |
xargs --verbose -0n2 mv
These next versions cannot handle single-quotes '
in filenames.
Using standard regex patterns
regex='\(.*/\)\(A \)\([0-9]\)$'
find . -depth -type d -regex "$regex" |
sed -n "s|$regex|'&' '\1\20\3'|p" |
xargs --verbose -n2 mv
To use extended regex paterns
regex='(.*/)(A )([0-9])$'
find . -depth -regextype posix-extended -type d -regex "$regex" |
sed -nr "s|$regex|'&' '\1\20\3'|p" |
xargs --verbose -n2 mv
The -depth
option is needed so that more deeply nested directories are renamed before any parent directory is renamed.
Note that the script does not test if a directory already exists with the same name as the new intended name.