LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This 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


Reply
  Search this Thread
Old 08-27-2016, 07:32 PM   #1
acacius
LQ Newbie
 
Registered: Jun 2015
Posts: 11

Rep: Reputation: Disabled
Renaming files with bash (round 2)


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
Why does the script do nothing?
 
Old 08-27-2016, 07:44 PM   #2
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
The problem is the spaces.

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)

Last edited by jpollard; 08-27-2016 at 07:50 PM.
 
Old 08-27-2016, 08:02 PM   #3
acacius
LQ Newbie
 
Registered: Jun 2015
Posts: 11

Original Poster
Rep: Reputation: Disabled
Ok I tried this but it still does nothing:

Code:
#!/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
 
Old 08-27-2016, 09:52 PM   #4
allend
LQ 5k Club
 
Registered: Oct 2003
Location: Melbourne
Distribution: Slackware64-15.0
Posts: 6,375

Rep: Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754
Quote:
if [[ "$CDTRACK" =~ "([[:alpha:][:blank:]]*)- ([[:digit:]]*) - (.*)$" ]]
The problem appears to be in the quoting of the regular expression.
Code:
  if [[ "$CDTRACK" =~ ([[:alpha:][:blank:]]+)"- "([[:digit:]]+)" - "(.+)$ ]]
works here. Note that I have changed from asterisk ( 0 or more occurrences ) to plus ( 1 or more occurrences ).

The 'for CDTRACK in *' construction is fine. You can check by adding an echo command to echo $CDTRACK.
 
Old 08-28-2016, 05:36 AM   #5
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192
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:
Code:
regex='([[:alpha:][:blank:]]+)- ([[:digit:]]+) - (.+)$'

...
if [[ "$CDTRACK" =~ $regex ]]
As you can see, this allows you to write the regex in a normal fashion without having to escape / quote bash sensitive items
 
1 members found this post helpful.
Old 08-28-2016, 08:15 AM   #6
allend
LQ 5k Club
 
Registered: Oct 2003
Location: Melbourne
Distribution: Slackware64-15.0
Posts: 6,375

Rep: Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754
Nice one! Thanks grail.

PS - I really do not like '([[:alpha:][:blank:]]+)' at the head of the regex. How do you process '634-5789'? https://www.youtube.com/watch?v=3KnhJSne-3Y
 
Old 08-28-2016, 10:35 AM   #7
ondoho
LQ Addict
 
Registered: Dec 2013
Posts: 19,872
Blog Entries: 12

Rep: Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053
i'm sorry but what is this mysterious BASH_REMATCH array? am i missing something?
 
Old 08-28-2016, 11:00 AM   #8
allend
LQ 5k Club
 
Registered: Oct 2003
Location: Melbourne
Distribution: Slackware64-15.0
Posts: 6,375

Rep: Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754Reputation: 2754
From 'man bash'
Quote:
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.
 
1 members found this post helpful.
Old 08-28-2016, 03:31 PM   #9
shabang
LQ Newbie
 
Registered: Aug 2016
Posts: 7

Rep: Reputation: Disabled
Quote:
Originally Posted by acacius View Post
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.

Last edited by shabang; 08-28-2016 at 03:50 PM.
 
  


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
Bash script for renaming files (all odd) snaggletooth1134 Programming 10 05-01-2012 12:26 AM
[SOLVED] Linux issue renaming files - BASH script giantanakim Programming 25 11-01-2011 12:21 PM
Bash, renaming files won't work mago Programming 11 04-02-2010 01:10 PM
bash help renaming files kahn Programming 6 06-16-2005 07:15 AM
How do I make a bash sheet for renaming files? Cyberian Linux - Newbie 16 03-16-2005 08:08 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 05:15 PM.

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