LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
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


Reply
  Search this Thread
Old 07-26-2005, 04:48 PM   #1
embsupafly
Member
 
Registered: Nov 2002
Location: ARIZONA
Distribution: Ubuntu
Posts: 44

Rep: Reputation: 15
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?
 
Old 07-27-2005, 11:04 AM   #2
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
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 druuna; 07-27-2005 at 11:07 AM.
 
Old 07-27-2005, 11:08 AM   #3
keefaz
LQ Guru
 
Registered: Mar 2004
Distribution: Slackware
Posts: 6,552

Rep: Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872
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
 
Old 07-27-2005, 11:11 AM   #4
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
@keefaz : Nice!

@embsupafly : Use keefaz' solution. Much more elegant and resource friendly.
 
Old 02-15-2007, 09:54 PM   #5
williamharwell
LQ Newbie
 
Registered: Feb 2007
Posts: 1

Rep: Reputation: 0
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.
 
Old 02-18-2007, 10:05 PM   #6
cfaj
Member
 
Registered: Dec 2003
Location: Toronto, Canada
Distribution: Mint, Mandriva
Posts: 221

Rep: Reputation: 31
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
 
Old 03-22-2010, 09:19 AM   #7
nefg
LQ Newbie
 
Registered: Oct 2007
Posts: 8

Rep: Reputation: 0
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
 
Old 03-22-2010, 10:03 AM   #8
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,011

Rep: Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194
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 "\"")
}
 
Old 03-26-2010, 10:18 AM   #9
nefg
LQ Newbie
 
Registered: Oct 2007
Posts: 8

Rep: Reputation: 0
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)
 
Old 03-26-2010, 10:36 AM   #10
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,011

Rep: Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194
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
 
Old 03-29-2010, 05:05 AM   #11
nefg
LQ Newbie
 
Registered: Oct 2007
Posts: 8

Rep: Reputation: 0
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
 
Old 03-29-2010, 08:53 AM   #12
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,011

Rep: Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194
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.
Old 03-31-2010, 05:16 AM   #13
nefg
LQ Newbie
 
Registered: Oct 2007
Posts: 8

Rep: Reputation: 0
Thanks grail. You are a Master. Total problem solved.
Best Regards
 
Old 03-31-2010, 06:58 AM   #14
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,011

Rep: Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194
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 "\""
}
 
Old 04-01-2010, 01:13 PM   #15
nefg
LQ Newbie
 
Registered: Oct 2007
Posts: 8

Rep: Reputation: 0
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
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Batch Script to rename files... jamie_barrow Linux - Newbie 16 06-14-2009 01:26 PM
BASH USAGE: mass files rename sirpelidor Linux - General 8 09-20-2005 12:36 AM
Bash backup script - If multiple files starting with a exist problem demoncheese Programming 2 07-29-2004 10:47 PM
Need script to rename files joe_stevensen Programming 5 12-05-2003 06:12 PM
Got a script to rename a batch of files? jamie_barrow Linux - General 1 08-08-2003 06:52 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:45 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration