LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   Rename files matching a list (http://www.linuxquestions.org/questions/programming-9/rename-files-matching-a-list-739558/)

Qu3ry 07-12-2009 11:44 AM

Rename files matching a list
 
Is there a way, preferably in python or BASH, to rename files from a list? for instance, track1.mp3, track2.mp3 should be renamed to the names stored in a file listing song names.

I have tried to loop a variable through directory listing and renamed them, only to find that filenames with spaces can't be assigned to a variable as a whole.

To solve the problem above, I have tried the read command in BASH, which enables the program reading line by line from a list. However, It was failed to pipe the results from directory listing to the read command.

Any help is appreciated !

catkin 07-12-2009 12:22 PM

Hello Qu3ry :)

Yes, it's possible. You've probably got some bash quoting issues. If you post your script we can take it from there.

Best

Charles

sutrannu 07-12-2009 02:28 PM

Code:

  for x in `seq 1 $(ls *.mp3|wc -l)`; do mv `ls *.mp3|head -$x|tail -1` `cat Track_List.txt|head -$x|tail -1|sed 's/[^0-9a-zA-Z]/_/g'`.mp3; done
Something like this would rename the mp3s in a folder with names from Track_List.txt if the number of mp3s matched the names in the file, they were in the same order, etc.
This is quick & dirty. Backup, and test first.
This will replace all non-alphanumeric characters with "_".

Qu3ry 07-14-2009 08:57 AM

How to combine these two?
 
Condition A
Code:

#!/bin/bash

for i in `ls *.mp3`; do echo i is $i; done

Condition B
Code:

#!/bin/bash

cat test.txt | while read j; do echo j is $j; done

The idea is to rename $i to $j. How to combine the first two conditions using the AND logical operator?

ie. If condition A and B is true, then rename i into j for each iteration

catkin 07-14-2009 10:19 AM

Hello Qu3ry :)

A and B are loops, not "conditions". In programming, a condition is a test -- equality, greater than, less than , existence etc.

How about reading the list of files into an array first and then loop through the lines of test.txt?

Code:

files=($(ls *.mp3))
i=0
cat test.txt | while read j
do
    echo mv "${files[ $i ]}" "$j"
    $(( i = i + 1 ))
done

The var=(<stuff>) creates var as an array and assigns the (whitespace separated) words of <stuff> to successive elements of the array. By default, whitespace is space, tab and newline . The form given above will work as long as there is no whitespace in the *.mp3 file names.

$(<stuff>) is doing the same as your `<stuff>` but is more robust.

$i is set to 0 before starting the loop because that is the index of the first element of the array.

Putting the $j in double quotes overcomes the problem of file names including spaces; it keeps the whole name together as a single word; without the double quotes, each (whitespace separated) word of $j would become a separate argument to the echo (later mv) command.

$(( <stuff> )) is for doing arithmetic.

The code is proof of concept (and not tested!) rather than smart. It doesn't check for test.txt having the same number of lines as there are *.mp3 files and it would be easier to read if $j was renamed to something meaningful like $track_name.

Best

Charles

Qu3ry 07-15-2009 11:38 AM

Thanks catkin for your help.

Some song names listed in the file ends with a trailing ^M, probably as a result of Windows-copy-and-paste thingy. I ran the script before using the dos2unix command. Songs are bearing weird endings. For instance, songname??.mp3

I have tried to rename them by using the rename command, but in vain.

Code:

#rename ^M.mp3 .mp3 *
Having tried \^M.mp3, "\^M.mp3" or ?.mp3, I found nothing work so far.

Qu3ry 07-15-2009 11:51 AM

BTW, the following msg was found in the prompt when running your script. ( I have the echo command removed btw)

Quote:

/usr/bin/match.sh: line 8: 1: command not found
/usr/bin/match.sh: line 8: 2: command not found
/usr/bin/match.sh: line 8: 3: command not found
/usr/bin/match.sh: line 8: 4: command not found
/usr/bin/match.sh: line 8: 5: command not found
/usr/bin/match.sh: line 8: 6: command not found
/usr/bin/match.sh: line 8: 7: command not found
/usr/bin/match.sh: line 8: 8: command not found
/usr/bin/match.sh: line 8: 9: command not found
/usr/bin/match.sh: line 8: 10: command not found
/usr/bin/match.sh: line 8: 11: command not found
/usr/bin/match.sh: line 8: 12: command not found
/usr/bin/match.sh: line 8: 13: command not found
/usr/bin/match.sh: line 8: 14: command not found
/usr/bin/match.sh: line 8: 15: command not found
/usr/bin/match.sh: line 8: 16: command not found
/usr/bin/match.sh: line 8: 17: command not found
/usr/bin/match.sh: line 8: 18: command not found
/usr/bin/match.sh: line 8: 19: command not found
/usr/bin/match.sh: line 8: 20: command not found
/usr/bin/match.sh: line 8: 21: command not found
/usr/bin/match.sh: line 8: 22: command not found
/usr/bin/match.sh: line 8: 23: command not found
/usr/bin/match.sh: line 8: 24: command not found

catkin 07-15-2009 12:20 PM

Hello Qu3ry :)

The Ctrl+M characters can be removed in the script:
Code:

ctlM=$'\r'
files=($(ls *.mp3))
i=0
cat test.txt | while read j
do
    echo mv "${files[ $i ]}" "${j%$ctlM}"
    $(( i = i + 1 ))
done

The form var=$'<stuff>' allows C escape sequences to be used in defining a string. C escape sequence \r is Ctrl+M.

Any text editor can be used to create the above script. If you are using an editor that allows insertion of Ctrl+M you wouldn't need the $ctlM variable. In vi you can enter it directly by pressing Ctrl+V then Ctrl+M. So you could replace "${j%$ctlM}" with "${j%$^M}".

Best

Charles

Qu3ry 07-15-2009 02:18 PM

This time is little bit different. I was about to rename a bunch of mp3 files having the following patterns:

1-01 track.mp3
1-02 track.mp3
1-03 track.mp3
1-04 track.mp3
1-05 track.mp3
1-06 track.mp3

2-01 song.mp3
2-02 song.mp3
2-03 song.mp3
2-04 song.mp3

How to merge all split files according to their track numbers? There is no info on how many parts are split for each song. The only info we know is they all have the same number prefixes.

The problem with for loop is that you have to know the largest number prefix in orker to loop. Also, is there a better way to extract their filenames?

Quote:

i=1
for i < 30
do
cat "$i"* > "$i".mp3
i = i + 1
done

Qu3ry 07-15-2009 02:30 PM

manipulating song lists
 
Problem with the tr command in BASH

I want to replace all filenames beginning with single digit prefixes into muliti-digits. For instance 1.song.mp3 into 01.song.mp3.

Code:

tr '^[1-9]\.$' '0[1-9]\.' <text.txt
It didn't work for unknown reasons.

Another interesting thing is that when text.txt is streamed through tr with the same filename as output, it didn't replace the old one with the new.

Code:

tr 'a' '1' <test.txt > text.txt
text.txt would be blank. why ? I have to use a new filename other than text.txt as output.

catkin 07-15-2009 02:39 PM

Quote:

Originally Posted by Qu3ry (Post 3608378)
BTW, the following msg was found in the prompt when running your script. ( I have the echo command removed btw)

Did you solve that issue? If not, try replacing
Code:

$(( i = i + 1 ))
with
Code:

let i=i+1

catkin 07-15-2009 02:41 PM

Quote:

Originally Posted by Qu3ry (Post 3608581)
This time is little bit different. I was about to rename a bunch of mp3 files having the following patterns:

1-01 track.mp3
1-02 track.mp3
1-03 track.mp3
1-04 track.mp3
1-05 track.mp3
1-06 track.mp3

2-01 song.mp3
2-02 song.mp3
2-03 song.mp3
2-04 song.mp3

How to merge all split files according to their track numbers? There is no info on how many parts are split for each song. The only info we know is they all have the same number prefixes.

What does the corresponding test.txt file look like?

Qu3ry 07-15-2009 02:53 PM

Quote:

Originally Posted by catkin (Post 3608612)
What does the corresponding test.txt file look like?

1.new year.mp3
2.linux.mp3
3.hello.mp3

etc...

Qu3ry 07-15-2009 03:10 PM

Quote:

Originally Posted by catkin (Post 3608609)
Did you solve that issue? If not, try replacing
Code:

$(( i = i + 1 ))
with
Code:

let i=i+1

after replacing it with "let i=i+1"

/usr/bin/match.sh: line 9: let: =: syntax error: operand expected (error token is "=")

catkin 07-15-2009 03:11 PM

Quote:

Originally Posted by Qu3ry (Post 3608594)
Problem with the tr command in BASH

I want to replace all filenames beginning with single digit prefixes into muliti-digits. For instance 1.song.mp3 into 01.song.mp3.

Code:

tr '^[1-9]\.$' '0[1-9]\.' <text.txt

I don't understand what the tr operands (SET1 and SET2 on the man page) are and anyway, what's going to happen when you get to 10.song.mp3? Might be easier to parse out the number (by ${name%%.*}) and format it as you want using printf.

Quote:

Originally Posted by Qu3ry (Post 3608594)
Code:

tr 'a' '1' <test.txt > text.txt
text.txt would be blank. why ? I have to use a new filename other than text.txt as output.

The shell empties the file after the > before running the command.


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