Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
 |
|
07-26-2005, 04:48 PM
|
#1
|
Member
Registered: Nov 2002
Location: ARIZONA
Distribution: Ubuntu
Posts: 44
Rep:
|
Help with Bash Script - Rename Multiple Files
Ok,
I am working on a bash script and I am in need of some major help if anyone is willing to assist!
We have a directory with about 17,000 image files in it. The image files are names in the format pic0001.eps, pic0002.eps, etc.. Each of these file names corresponds to a real name such as Red Cross, Sony, etc. What we have in addition to the files, is (1) in a large text file, a sorted alphabetical listing of all of the filenames, and (2) a seperate text file of the real names that the filenames are supposed to be that are listed in the same corresponding order as the text file with the filenames.
I am struggling to find a way to get a bash file to enter the directory with the image files and text files and look at the text file with the filenames, select this file and rename the file according to the real name associated with it in the other textfile with the real names while keeping the same file extention.
Anyone have ideas?
|
|
|
07-27-2005, 11:04 AM
|
#2
|
LQ Veteran
Registered: Sep 2003
Posts: 10,532
|
Hi,
If I understand correctly then this should do what you want:
Code:
#!/bin/bash
# sorted list with real file names
REALNAME="/path/to/sorted.real.names"
# list with wanted name
WANTEDNAME="/path/to/wanted.names"
# directory that holds pictures/files
PICDIR="/path/to/picture/directory"
sdiff -t ${REALNAME} ${WANTEDNAME} | \
sed 's/ [ ]*| /|/' | \
awk -v PICDIR=${PICDIR} -F"[.|]" '{ print "mv "PICDIR"/"$1"."$2" \""PICDIR"/"$3"."$2"\"" }' > /tmp/rename-this
. /tmp/rename-this
#sdiff -t ${REALNAME} ${WANTEDNAME} | sed 's/ [ ]*| /|/' | \
# awk -v PICDIR=${PICDIR} -F"[.|]" '{ print "mv "PICDIR"/"$1"."$2" \""PICDIR"/"$3"."$2"\"" }' | bash
A little breakdown of the above:
The first three variables (REALNAME, WANTEDNAME and PICDIR) need to point to the appropriate files/dirs. You need to change this before you start testing/trying.
sdiff -t ${REALNAME} ${WANTEDNAME} This merges the file holding the actual names with the file holding the wanted names. I do undestand that these files correspond, this needs to be so for the correct working of this 'script'.
The -t option expands tabs to spaces, which will make life a bit easier for what comes next.
Part of this output:
Code:
pic0001.esp | Sony
pic0002.esp | Red Cross
sed 's/ [ ]*| /|/' This replaces the 'middle part' (spaces | spaces) with just a |
Part of this output:
Code:
pic0001.esp|Sony
pic0002.esp|Red Cross
awk -v PICDIR=${PICDIR} -F"[.|]" '{ print "mv "PICDIR"/"$1"."$2" \""PICDIR"/"$3"."$2"\"" }'
LOL This might need a longer explenation all by it self, which I will not do.....
What it does? It creates a legal move statement (mv x y). It also surrounds both source and destination with double quotes (mv "x" "y"), this to take care of special chars (spaces being the obvious one).
Part of this output:
Code:
mv "/path/to/picture/directory/pic0001.esp" "/path/to/picture/directory/Sony.esp"
mv "/path/to/picture/directory/pic0002.esp" "/path/to/picture/directory/Red Cross.esp"
The script gives you 2 option to continue:
1The one that is 'active' at the moment ) Put the output in a file (/tmp/rename-this) and parse the file (. /tmp/rename-this).
2) pipe the output of the awk command to bash ( awk ... | bash).
I like the second one better.
Hope this gets you going again.
Last edited by anon237; 07-27-2005 at 11:07 AM.
|
|
|
07-27-2005, 11:08 AM
|
#3
|
LQ Guru
Registered: Mar 2004
Distribution: Slackware
Posts: 6,858
|
I have a perl solution :
PHP Code:
#!/usr/bin/perl
my $dir = '/path/to/images/directory';
my $names = '/path/to/file/with/the/wanted/names';
my $files = '/path/to/file/with/the/real/name';
chdir $dir or
die "Could not change dir to $dir: $!\n";
open NAMES, $names or die "Could not open $names: $!\n";
open FILES, $files or die "Could not open $files: $!\n";
my $name = <NAMES>;
chomp $name;
my $file = <FILES>;
chomp $file;
while($name && $file) {
print "renaming $file to $name...\n";
rename $file, $name;
$name = <NAMES>;
chomp $name;
$file = <FILES>;
chomp $file;
}
close NAMES;
close FILES;
|
|
|
07-27-2005, 11:11 AM
|
#4
|
LQ Veteran
Registered: Sep 2003
Posts: 10,532
|
@keefaz : Nice!
@embsupafly : Use keefaz' solution. Much more elegant and resource friendly.
|
|
|
02-15-2007, 09:54 PM
|
#5
|
LQ Newbie
Registered: Feb 2007
Posts: 1
Rep:
|
Multiple dots in a file name
The first example works great on files with only one dot. Ex: picture1.jpg. But what if I need to do this on files with multiple dots such as picture.1.jpg
I would like to change the filename except for the final dot and extension.
Any ideas?
The second example written in Perl does not leave the extension intact.
Thanks
Last edited by williamharwell; 02-15-2007 at 09:55 PM.
|
|
|
02-18-2007, 10:05 PM
|
#6
|
Member
Registered: Dec 2003
Location: Toronto, Canada
Distribution: Mint, Mandriva
Posts: 221
Rep:
|
Quote:
Originally Posted by embsupafly
Ok,
I am working on a bash script and I am in need of some major help if anyone is willing to assist!
We have a directory with about 17,000 image files in it. The image files are names in the format pic0001.eps, pic0002.eps, etc.. Each of these file names corresponds to a real name such as Red Cross, Sony, etc. What we have in addition to the files, is (1) in a large text file, a sorted alphabetical listing of all of the filenames, and (2) a seperate text file of the real names that the filenames are supposed to be that are listed in the same corresponding order as the text file with the filenames.
I am struggling to find a way to get a bash file to enter the directory with the image files and text files and look at the text file with the filenames, select this file and rename the file according to the real name associated with it in the other textfile with the real names while keeping the same file extention.
Anyone have ideas?
|
What do the text files contain?
Is there one file with the current file name and another with the new file name?
Is there a line-to-line correspondence between the files?
Do the files contain the full names of the files, or just the part before the suffix ("extension" in Windows-speak)?
I would use something like this, but without more details on the format of the files, I cannot tell whether it will work:
Code:
exec 3<textfile1
exec 4<textfile2
cd /path/to/directory/with/images
while read file <&3; read name <&4
do
mv "$file" "$name"
done
|
|
|
03-22-2010, 09:19 AM
|
#7
|
LQ Newbie
Registered: Oct 2007
Posts: 8
Rep:
|
It works
The solution given by cfaj works!
Code:
exec 3<textfile1
exec 4<textfile2
cd /path/to/directory/with/images
while read file <&3; read name <&4
do
mv "$file" "$name"
done
Thanks
|
|
|
03-22-2010, 10:03 AM
|
#8
|
LQ Guru
Registered: Sep 2009
Location: Perth
Distribution: Arch
Posts: 10,039
|
Assuming both files checked just place after name of script separated by space:
Code:
#!/usr/bin/awk -f
BEGIN{
file1 = ARGV[1]
file2 = ARGV[2]
}
NR{
getline < file1
out1 = $0
getline < file2
out2 = $0
system("mv \"" out1 "\" \"" out2 "\"")
}
|
|
|
03-26-2010, 10:18 AM
|
#9
|
LQ Newbie
Registered: Oct 2007
Posts: 8
Rep:
|
Thanks to "grail". This awk script works too. However the NR in the script seems to be reduntant i.e. it works without the NR in the script code. Also when executing either as an executable script or just code typed in fro command line it goes through the renaming sequence twice (it is harmless though)
|
|
|
03-26-2010, 10:36 AM
|
#10
|
LQ Guru
Registered: Sep 2009
Location: Perth
Distribution: Arch
Posts: 10,039
|
Yeah I am not sure what I was thinking there (looking back at it) :$
Although as I am still on the learning side of awk i have also discovered
the variable assignment can be done on one line too:
Code:
getline out1 < file1
|
|
|
03-29-2010, 05:05 AM
|
#11
|
LQ Newbie
Registered: Oct 2007
Posts: 8
Rep:
|
Also ( I think) why it goes on repeating the "action" after renaming of files is completed, is because awk repeats the test for total nos lines of input. In this case two files are input. So it repeats for total nos lines for both files. The renaming is complete when it goes through the first file and balance actions are redundant. If you give it three parameters eg file1 file2 file2, it repeats action for total nos lines for all three files. This can be verified by adding
END{
print "NR is - " NR
}
at end of code.
Thanks and
Best Regards
|
|
|
03-29-2010, 08:53 AM
|
#12
|
LQ Guru
Registered: Sep 2009
Location: Perth
Distribution: Arch
Posts: 10,039
|
So like I said before ... always learning
Code:
#!/usr/bin/awk -f
BEGIN{
file1 = ARGV[1]
file2 = ARGV[2]
}
(getline out1 < file1) > 0{
getline out2 < file2
print | "mv \"" out1 "\" \"" out2 "\""
}
This stops when the first file runs out of lines 
|
|
1 members found this post helpful.
|
03-31-2010, 05:16 AM
|
#13
|
LQ Newbie
Registered: Oct 2007
Posts: 8
Rep:
|
Thanks grail. You are a Master. Total problem solved.
Best Regards
|
|
|
03-31-2010, 06:58 AM
|
#14
|
LQ Guru
Registered: Sep 2009
Location: Perth
Distribution: Arch
Posts: 10,039
|
Can't keep a good man down (although I fear there are true gurus around who can do better):
Code:
#!/usr/bin/awk -f
ARGV[1] == FILENAME{
getline out2 < ARGV[2]
print "mv \"" $0 "\" \"" out2 "\""
}
|
|
|
04-01-2010, 01:13 PM
|
#15
|
LQ Newbie
Registered: Oct 2007
Posts: 8
Rep:
|
Thanks to grail. It took time to "digest" the compact code. To work you have to add "|bash" to the end of the command however.
Best Regards
|
|
|
All times are GMT -5. The time now is 06:48 PM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|