See http://mywiki.wooledge.org/BashFAQ/001 for what you're doing wrong. You have to be careful about using the output of a command with spaces in it, to make sure you don't use it in a context where it will be word-split.
In your specific example, you don't actually need a regex. Shell glob expressions will do the trick.
for i in [0-9][0-9]' -'*; do
mv "$i" "${i// /_}"; # / at start of pattern = all matches.
done
Or more usefully for messing around with filenames:
- prename (perl-based renamer, packaged in Debian/Ubuntu in the
perl
package)
mmv
'foo*.mp3' 'bar#1.mp3'
So your goal of replacing track numbers with Eagles
would be:
prename 's/[0-9]+ -/Eagles -/' *.mp3
Or tack Eagles -
onto the front of every filename.
prename 's/^/Eagles - /' [0-9]*.mp3 # or:
prename '$_ = "Eagles - " . $_' [0-9]*.mp3 # you aren't limited to the s// operator, it really does eval as perl code.
Notice how you can use shell globs to select files to run prename
on, so your actual pattern doen't have to avoid matching filenames you can filter other ways. If you want to use /
in your pattern (to move files to a subdirectory, for example), I suggest using s{pat}{repl}
syntax. So much nicer than a sed
one-liner that turns into a forest of \/
.
There's a shopt -s extglob
bash option, but you're probably better off just using regexes instead of that, unless you're writing shell scripts for max efficiency. (e.g. programmable completion functions that run every time someone presses tab
).