Is there a linux command like mv but with regex?
For example I want to mv (.*?).sql $1.php
,
is there a command that lets me specify renaming patterns?
Solution 1:
As others have mentioned, rename
is good at this, but read the man page (man rename
) before you try it. There are at least two entirely different tools out there called rename
and which one you have will depend on your distribution. Calling them incorrectly can be dangerous.
Here's the man page for the perl-based version by Larry Wall that ships with Ubuntu. You give it a perl expression like rename 's/\.sql$/.php/' *.sql
Here's the man page for the rename that ships with older Red Hat and CentOS distributions. Usage is simple string substitution like rename .sql .php *.sql
You could also use a bash one-liner to process each file one at a time:
$ for f in *.sql; do mv -i "$f" "${f%%.*}.php"; done
Solution 2:
There's rename(1)
, which doesn't use regexes, but can solve your problem:
rename .sql .php *.sql
There's also mmv(1)
, but I'm unfamiliar with how it works.
Solution 3:
You could also try entering
for i in $(\ls -d *.sql)
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done
Or to make it use regex's change it slightly to
for i in $(\ls -d | egrep -e '.*\.sql')
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done
for a bit of shell coding fun.
Solution 4:
Being a plumber, I like pipes :)
Note: this answer is verbose - as a newbee I appreciate it when someone who knows takes the time to explain, so I am paying 'forward'. If you are not a newbee, please excuse the length and verbosity.
ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/' | bash
Where:
ls -1 *_201[67][0-9]*
lists all files matching the pattern, in this case I am looking for files with the date in the filename in the form 'YYYYMMDD'
sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'
# : | | | | | | | |: :
# : |^2....^ ^3..................^^4.......^ |: :
# :^1..............................................................^: :
# /................filename.................pattern................./...mkdir...and....mv...command.../
^1: 1st capture group - the entire filename
^2: 2nd capture group - the 1st part of the filename pattern
^3: 3rd capture group - the 2nd filename part - here, the date as 'YYYYMMDD'
^4: 4th capture group - optional filename part between the date and the extension, and the extension itself
Sooooo....if I have a file named
CallLog_555123412_20161231-214403.7z
...then
mkdir -p \2\/\3; mv \1 \2\/\3\/\1
actually means
# make directory and sub-directory
mkdir -p CallLog_555123412/20161231
# move file from current directory to sub-sub-directory just created
mv CallLog_555123412_20161231-214403.7z CallLog_555123412/20161231/CallLog_555123412_20161231-214403.7z
Note that the output of the sed command is piped through to 'bash' to execute it. In order to first see the proposed file moves WITHOUT actually moving them, first remove the '| bash' at the end, and try it like so:
ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'
This will not make any changes at all, but you will see the command that will be executed IF you run it with '| bash' tagged on the end.
This is useful because you can create any sub-directories you want from parts in the filename, or anything else you add to the 'replacement' text in the sed command. Note that sed requires a lot of escape characters, though.
SED Regex brackets:
(...) require escaping for capture grouping --> \(...\)
{m,n} require escaping for quantifying previous object --> \{m,n\}
/ requires escaping in the replacement string --> \/
[...] DO NOT require escaping for character classes
\1 in the replacement string refers to the 1st captured group, and so on...
SECURITY WARNING: NEVER PIPE ANYTHING TO 'bash' UNLESS YOU FULLY UNDERSTAND THE OUTCOME...
Hope that helps clear some blockages :)
Solution 5:
Install mmv
, then do this:
mmv "*.sql" "#1.php"