Shell How Can I Renames Files with Wildcards?

In the order of priority, here is what I would like to achieve.

I have files with names like, "07 - - ?tudes d'ex?cution transcendence - Eroica.flac" in which the symbol '?' appears in the place of letter 'e'. I would like a command line, or a script, which will allow the replacement of ? with e. Preferably recursive.

I want to remove the '## - ' appearing before the name of the music .

I want to truncate any file name longer than 64 characters, but keeping the file extension
find . -type f|while read a;do echo -n mv '"'$a'"';b=${a//\?/e};b=${b/\ -\ -\ /\-};base=${b%.*};ext=${b##*.};base=${base:0:64};echo ' "'$base.$ext'"';done
needs bash (wont work with sh)
If I understand you right, you're trying to accomplish multiple things here.

First: It seems to me that your filenames contain unicode characters. The "?" in "?tudes" is probably an E with an accent of it. And to be clear: While it is displayed on your screen as "?", its binary representation is probably not that of the real question mark. If you tried to perform a search for files with a real question mark in it, you would not find these. If you set up your language environment variables correctly, and use a terminal emulator that handles unicode correctly, then it will suddenly display correctly as "Études", and maybe you would like that. Would that be a simpler solution?

Failing that, you'll have to do the renames. My personal answer to that is very simple-minded: I like to make a file listing using "ls > /tmp/foo". That gives me a text file which has all the current (wrong) file names in it. Then I use a small script (in awk, python, or just an emacs macro) to change every line in that file to the following format:
mv "name" "newname"
mv "Sonata \"Les Adieux\"" "Beethoven Sonata no. 26 in Eb \"Les Adieux\""
All I'm doing is: prefix every line with "mv", then duplicate the name (make two copies), and put them in double quotes. If you want to be thorough, you should first take any existing double quotes, and escape them (by turning them into the string \"). I gave an example in for the file Sonata "Les Adieux" in the code block above. Anyway, by putting the list of files into a text file, we have now decoupled the problem into two, which are easier: Editing the file names, and doing the actual renames. In particular, you can now take an editor and read and check that the new names are the way you like.

Second: Let's assume you really do want to remove unicode names, and turn them into ASCII (I would be in favor of that, to prevent display problems). This is actually really hard to do in general. There is no single universal transliteration table that I know of. And doing the transliteration will sometimes change the length of the string: While a sensible conversion for the French "É" is "E" (same string length), for the German letters "Ä" it is "Ae" and "ß" is "ss". My proposal would be: You probably only have a limited list of non-ASCII characters. Do them by hand, in a good editor that can display Unicode, either directly, or as decimal numbers. Then use search and replace in an editor.

Third: Be careful with shortening file names to 64 characters. While covecat's script should work, it may have a nasty side effect: If you have two original files whose names are identical in the first 64 characters, then either of two things will happen: your rename script will crash (bad), or the second file will overwrite the first one (worse). Again, this is something that you could do by creating a script, then hand-editing the script to make sure it is correct.

Finally, good taste in music. Who is playing? Do you know the Lazar Berman recordings? He was amazing. I remember when that recording became available in the west in the 70s, and caused amazement: In the era before maniacs like Yuja Wang and Lang Lang, how could anyone play like that? I mean except for Cziffra, but he was differently crazy.


Staff member
rename(1) (FreeBSD man page site links to the wrong one due to name clashes) from sysutils/p5-File-Rename is extremely useful. Yes, it's a Perl module but it also has a very useful /usr/local/bin/rename you can use from the command line.

% /usr/local/bin/rename
    rename [ -h|-m|-V ] [ -v ] [ -0 ] [ -n ] [ -f ] [ -d ]
    [ -e|-E perlexpr]*|perlexpr [ files ]

You can use regular expressions to rename files.

Due to a lack of a proper link, the first part of the man page:
       rename - renames multiple files

       rename [ -h|-m|-V ] [ -v ] [ -0 ] [ -n ] [ -f ] [ -d ]
       [ -e|-E perlexpr]*|perlexpr [ files ]

       "rename" renames the filenames supplied according to the rule specified
       as the first argument.  The perlexpr argument is a Perl expression
       which is expected to modify the $_ string in Perl for at least some of
       the filenames specified.  If a given filename is not modified by the
       expression, it will not be renamed.  If no filenames are given on the
       command line, filenames will be read via standard input.

   Examples (Larry Wall,  1992)
       For example, to rename all files matching "*.bak" to strip the
       extension, you might say

               rename 's/\.bak$//' *.bak

       To translate uppercase names to lower, you'd use

               rename 'y/A-Z/a-z/' *

   More examples (2020)
       You can also use rename to move files between directories, possibly at
       the same time as making other changes (but see --filename)

               rename 'y/A-Z/a-z/;s/^/my_new_dir\//' *.*

       You can also write the statements separately (see -e/-E)

               rename -E 'y/A-Z/a-z/' -E 's/^/my_new_dir\//' *.*