[SOLVED] sed - Rule: "leftmost match, longest possible string, zero also matches."?
ProgrammingThis 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.
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.
16 mat nai - Jimmy Nguyen [NCT 1188596568].mp3
Nho ve em - Jimmy Nguyen [NCT 4035860162].mp3
Buon thu qua - Jimmy Nguyen [NCT 9734938264].mp3
Nho ve em - Jimmy Nguyen [NCT 5629480849].mp3
Chiec nhan ngay xua - Jimmy Nguyen [NCT 1268575536].mp3
Nhung gi toi uoc ao - Jimmy Nguyen [NCT 2820242089].mp3
...
I want to cut the tail to make it to:
Code:
16 mat nai - Jimmy Nguyen.mp3
Nho ve em - Jimmy Nguyen.mp3
Buon thu qua - Jimmy Nguyen.mp3
Nho ve em - Jimmy Nguyen.mp3
Chiec nhan ngay xua - Jimmy Nguyen.mp3
Nhung gi toi uoc ao - Jimmy Nguyen.mp3
...
I try to using a following command:
Code:
$ for f in *; do mv "$f" `echo "$f" | sed 's/ \[NCT [0-9]*\]//'`; done
or:
Code:
$ for f in *; do mv "$f" `echo "$f" | sed 's/\(.*\) \[NCT [0-9]*\].mp3$/\1.mp3/'`; done
but it didn't work:
Quote:
mv: target `Nguyen.mp3' is not a directory
I don't know why? I think it related to above rule. Can anyone help me to explain that.
The problem is most likely the spaces in the filenames. Your shell treats them as word separators, so your mv command sees the final string as being a directory name to move the rest of the entries into. Double-quoting the string that generates the new filename will probably fix it.
But my favorite way to handle spaces (other than simply not putting them in filenames to begin with) is to temporarily change the shell's internal field separator so that it doesn't treat them as places to divide words.
Code:
oldIFS=$IFS #first save the current values (default is space, tab, newline)
IFS='
' #changes the separator to newline only
<Run your commands here>
IFS=$oldIFS #reset the initial values
PS: Instead of this:
Code:
`echo "$f" | sed 's/ \[NCT [0-9]*\].mp3$//'`
Try this:
Code:
"$(sed 's/ \[NCT [0-9]*\].mp3$//')" <<<"$f"
The <<< here string directs the output of the variable directly to stdin, meaning you don't have to use echo and pipes. And $() is the recommended way to nest commands. Using ` backticks is discouraged.
if you have Python and don't mind a script for that, you use the script here
Code:
# ls -1
16 mat nai - Jimmy Nguyen [NCT 1188596568].mp3
Buon thu qua - Jimmy Nguyen [NCT 9734938264].mp3
Chiec nhan ngay xua - Jimmy Nguyen [NCT 1268575536].mp3
Nho ve em - Jimmy Nguyen [NCT 4035860162].mp3
Nho ve em - Jimmy Nguyen [NCT 5629480849].mp3
Nhung gi toi uoc ao - Jimmy Nguyen [NCT 2820242089].mp3
# python filerenamer.py -p " \[.*\]" -e "" -l "*mp3"
==>>>> [ /home/test/Chiec nhan ngay xua - Jimmy Nguyen [NCT 1268575536].mp3 ]==>[ /home/test/Chiec nhan ngay xua - Jimmy Nguyen.mp3 ]
==>>>> [ /home/test/Nho ve em - Jimmy Nguyen [NCT 4035860162].mp3 ]==>[ /home/test/Nho ve em - Jimmy Nguyen.mp3 ]
==>>>> [ /home/test/Nho ve em - Jimmy Nguyen [NCT 5629480849].mp3 ]==>[ /home/test/Nho ve em - Jimmy Nguyen.mp3 ]
==>>>> [ /home/test/16 mat nai - Jimmy Nguyen [NCT 1188596568].mp3 ]==>[ /home/test/16 mat nai - Jimmy Nguyen.mp3 ]
==>>>> [ /home/test/Buon thu qua - Jimmy Nguyen [NCT 9734938264].mp3 ]==>[ /home/test/Buon thu qua - Jimmy Nguyen.mp3 ]
==>>>> [ /home/test/Nhung gi toi uoc ao - Jimmy Nguyen [NCT 2820242089].mp3 ]==>[ /home/test/Nhung gi toi uoc ao - Jimmy Nguyen.mp3 ]
16 mat nai - Jimmy Nguyen [NCT 1188596568].mp3
Nho ve em - Jimmy Nguyen [NCT 4035860162].mp3
Buon thu qua - Jimmy Nguyen [NCT 9734938264].mp3
Nho ve em - Jimmy Nguyen [NCT 5629480849].mp3
Chiec nhan ngay xua - Jimmy Nguyen [NCT 1268575536].mp3
Nhung gi toi uoc ao - Jimmy Nguyen [NCT 2820242089].mp3
and I ran these seders on it and got the following output
Code:
$ sed 's? \{1,\}\[?[?' test.txt |\
> sed 's?^\([^\[]*\)\[[^.]*?\1?'
16 mat nai - Jimmy Nguyen.mp3
Nho ve em - Jimmy Nguyen.mp3
Buon thu qua - Jimmy Nguyen.mp3
Nho ve em - Jimmy Nguyen.mp3
Chiec nhan ngay xua - Jimmy Nguyen.mp3
Nhung gi toi uoc ao - Jimmy Nguyen.mp3
if your files are all in the same directory you could do this
Code:
for f in *.mp3
g="$(echo $f |sed 's? \{1,\}\[?[?' |\
sed 's?^\([^\[]*\)\[[^.]*?\1?')"
if [ "$f" != "$g" ]; then
mv "$f" "$g"
fi
done
The problem is most likely the spaces in the filenames. Your shell treats them as word separators, so your mv command sees the final string as being a directory name to move the rest of the entries into. Double-quoting the string that generates the new filename will probably fix it.
Thanks for your explain.
Quote:
Originally Posted by David the H.
But my favorite way to handle spaces (other than simply not putting them in filenames to begin with) is to temporarily change the shell's internal field separator so that it doesn't treat them as places to divide words.
Code:
oldIFS=$IFS #first save the current values (default is space, tab, newline)
IFS='
' #changes the separator to newline only
<Run your commands here>
IFS=$oldIFS #reset the initial values
I know this way, but I always want to do that using one-line command.
Quote:
Originally Posted by David the H.
PS: Instead of this:
Code:
`echo "$f" | sed 's/ \[NCT [0-9]*\].mp3$//'`
Try this:
Code:
"$(sed 's/ \[NCT [0-9]*\].mp3$//')" <<<"$f"
The <<< here string directs the output of the variable directly to stdin, meaning you don't have to use echo and pipes. And $() is the recommended way to nest commands. Using ` backticks is discouraged.
(assuming you're using bash, of course)
Oh, now I know about here string, but can you show me a full command to do this?
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.