bash - Batch rename files that do not match pattern
2014-07
I do not have programming experience and mostly use one-liner or sometimes more to get the job done. I am having problem to batch rename the files that do not match a particular pattern.
Sample file-names from directory:
Meeting_Packages.pdf
13_textfile0
19_textfile0
23_textfile0
29_textfile0
33_textfile1
45_textfile0
5_textfile3
Membership.pdf
13_textfile1
19_textfile1
23_textfile1
29_textfile1
34_textfile0
46_textfile0
6_textfile0
xyz2009.pdf
13_textfile2
19_textfile2
23_textfile2
29_textfile2
34_textfile1
47_textfile0
6_textfile1
meeting.ics
I want to rename the files e.g. Meeting_Packages.pdf
, Membership.pdf
, meeting.ics
and xyz2009.pdf
to the file from where they came (input file). Actually it is output of ripmime
with mails as xx_textfilex
and others are attachments. I want to name attachments as the original input file
My Code:
#!/bin/bash
FILES=*.mime
for f in $FILES
do
echo "Processing $f"
#rip mails into attachments and text files also add a prefix to text files
ripmime -i $f -d ~/test/ripmime --prefix
#Remove white spaces from files
rename 's/ /_/g' ~/test/ripmime/*
#rename attachments as original input files
rename 's/\[^0-9]/'$f/ ~/test/ripmime/*
done
My problem is the last rename line where I try to filter files other than xx_textfilex
and rename. I tried different regular expressions but could not do that. I can select and rename the textfiles by:
rename 's/textfiles/'$f/ ~/test/ripmime/*
but I need the inverse of that and rename files other then textfiles.
How can I do this?
I use https://gist.github.com/995151
rename 's/\.bak$//' *.pdf
You can combine ls
and grep -v
:
ls | grep -v ".*textfile.*" | while read filename; do
# rename $filename to something
done
I've got some files like this:
database1-backup-01-01-2011.sql
database2-backup-01-01-2011.sql
...etc. I want to rename them to add AM, like this:
database1-backup-01-01-2011-AM.sql
database2-backup-01-01-2011-AM.sql
What's the most concise way to do that from the bash shell?
Another option:
for i in *.sql ; do
mv -v $i ${i%.sql}-AM.sql
done
This loops through all the .sql files and renames them to end in -AM.sql instead.
PROTIP: Use $(command)
instead of `command`
in your scripts (and command-lines), it makes quoting and escaping less of a nightmare.
Try this little script:
#!/bin/sh
FILES=`ls *.sql`
for FILE in ${FILES}
{
BASE=`basename ${FILE} .sql`
mv ${FILE} ${BASE}-AM.sql
}
I just typed that from memory so if it doesn't work 100% don't blame me (i.e., back up your data first ;) )
How it works:
Collect all files into a variable (you could put this inside the for instead but I like to keep things easy to read):
FILES=`ls *.sql`
Loop through each file:
for FILE in ${FILES} { ... }
Get the filename without .sql:
BASE=`basename ${FILE} .sql`
Rename the file, adding -AM.sql to the base name:
mv ${FILE} ${BASE}-AM.sql
Using the Perl script version of rename
:
rename 's/\.sql$/-AM$&/' *.sql
Using the util-linux-ng
version of rename
(but only if ".sql" only appears at the end of the filename):
rename .sql -AM.sql *.sql
Using mmv
:
mmv '*.sql' '#1-AM.sql'
Since a Perl script has been suggested, here's a Ruby script to do the same:
`ls *.sql`.split("\n").each do |filename|
new_filename = filename.split('.').join('-AM.')
`mv #{filename} #{new_filename}`
end