Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
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.
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.
I am reading the "Bash Cookbook" from O'Reilly and came across this script (pg. 123 in the book) to rename burned CD tracks so that the filenames will only be track numbers:
Code:
#!/usr/bin/env bash
for CDTRACK in *
do
if [[ "$CDTRACK" =~ "([[:alpha:][:blank:]]*)- ([[:digit:]]*) - (.*)$" ]]
then
echo Track ${BASH_REMATCH[2]} is ${BASH_REMATCH[3]}
mv "$CDTRACK" "Track${BASH_REMATCH[2]}"
fi
done
However, when I create the file, and try the script, nothing happens.
Code:
maxim@debian2:~$ touch "Ludwig Van Beethoven - 04 - Coriolan Overture, Op. 62.ogg"
maxim@debian2:~$ ls
Ludwig Van Beethoven - 04 - Coriolan Overture, Op. 62.ogg
maxim@debian2:~$ bash /home/maxim/bash_scripts/test.sh
maxim@debian2:~$ ls
Ludwig Van Beethoven - 04 - Coriolan Overture, Op. 62.ogg
The "for CDTRACK in *" expands into "for CDTRACK in Ludwig Van Beethoven - 04 - Coriolan Overture, Op. 62.ogg",
thus every value of CDTRACK is one of "Ludwig", "Van", "Beethoven", "-", "04", "-", "Coriolan", "Overture", ",", "Op.", "62.ogg", and not the list of filenames with the spaces. The result is none of the matching succeeds.
If there are no subdirectories, you likely would have a better result using
Code:
find . -print | while read CDTRACK ; do
...
done
Or anything that will provide the filenames one at a time ("ls -C1" comes to mind as an alternative to using find)
#!/usr/bin/env bash
ls | while read -r CDTRACK ;
do
if [[ "$CDTRACK" =~ "([[:alpha:][:blank:]]*)- ([[:digit:]]*) - (.*)$" ]]
then
echo Track ${BASH_REMATCH[2]} is ${BASH_REMATCH[3]}
mv "$CDTRACK" "Track${BASH_REMATCH[2]}"
fi
done
allend has solved the problem, so I will make a suggestion. It has been my experience that when using regular expressions in bash, which are more complicated that standard text, you are better
served to place your expression in a variable using single quotes to preserve all the special characters and then calling the variable raw, ie. without quotes.
So using your current example, my approach would be:
An additional binary operator, =~, is available, with the same precedence as == and !=. When it is used, the string to the right of the operator is considered an extended regular expression and matched accordingly (as in regex(3)).
...
Substrings matched by parenthesized subexpressions within the regular expression are saved in the array variable BASH_REMATCH. The element of BASH_REMATCH with index 0 is the portion of the string matching the entire regular expression. The element of BASH_REMATCH with index n is the portion of the string matching the nth parenthesized subexpression.
I am reading the "Bash Cookbook" from O'Reilly and came across this script (pg. 123 in the book) to rename burned CD tracks so that the filenames will only be track numbers:
Code:
#!/bin/bash
x=1
for i in *
do
echo mv "$i" $(printf "%02d.${i##*.}\n" $x)
(( x++ ))
done
This will rename your filenames to numbers as you wanted in your post. Your files will be rename to 01.ext, 02.ext. 03.ext,..etc. The .ext is the original file extension of the files.
**Note: If you want the track numbers to be 001.ext, 002.ext, 003.ext, etc. Replace "%02d.${i##*.}\n" with "%03d.${i##*.}\n"
If you don't want any extensions with the track numbers, replace the code with echo mv "$i" $(printf "%02d\n" $x)
Continuing on...
The quotes around the variable "$i" will handle filenames with spaces or any other odd characters.
The echo command is like a preview on how the script will execute the code. This will not do anything to your files until you remove the echo statement. If happy with the preview, then remove the echo statement and run the script again.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.