Just use perl-rename
(found as rename
on Debian and Ubuntu etc). First, for testing, let's create an awful name:
touch " a truly “horrible”, ‘awful’"$'\n'"name with a newline and *globs*, and even a 'single' quote or two! .txt"
This is what that looks like:
$ ls
' a truly “horrible”, ‘awful’'$'\n''name with a newline and *globs*, and even a '\''single'\'' quote or two! .txt'
Note that that there is a literal newline character, if you try to loop over this (badly), you will see:
$ for f in *; do echo "$f"; done
a truly “horrible”, ‘awful’
name with a newline and *globs*, and even a 'single' quote or two! .txt
So, that name has most if not all the problems you'll be facing. Now, use rename
to get rid of the bad characters:
$ rename 's/[*“”‘’\n<|>"[\]]//g; s/:/-/g; s/\s+/ /g; s/^\s*//; s/\s+\././g; '"s/'//g" *
$ ls -N
a truly horrible, awfulname with a newline and globs, and even a single quote or two!.txt
As you can see, that removed all of the bad things you were looking for (as far as I could tell since I only had your sed attempt to go on). You could fit this into your script like this:
for filename in "${@}"; do
rename 's/[*“”‘’\n<|>"[\]]//g;
s/:/-/g;
s/\s+/ /g;
s/^\s*//;
s/\s+\././g; '"s/'//g" "$filename"
done
Explanation
The basic syntax is very similar to sed
, you are using the same substitution operator. The regular expressions are:
s/[*“”‘’\n<|>"[\]]//g;
: substitute every occurrence of *
, “
, ”
, ‘
, ’
, \n
, <
, |
, >
, "
, [
, or `] with nothing, delete them.
s/:/-/g
: substitute every occurrence of any whitespace character (basically a space, a tab or a newline) with -
.
s/\s+/ /g
: substitute all occurrences of one or more consecutive whitespace characters with a single space.
*s/^\s*//
: remove all leading whitespace from the beginning of the file name,
s/\s+\././g
: remove all occurrences of one or more whitespace characters that come before a .
.
"s/'//g"
: remove all single quotes. Note how the whole command is rename '...'
and then I have added "s/'//g"
. This is because you cannot escape a single quote within a single-quoted string, so I had to close the single-quoted string and open a new, double quoted one to deal with the '
characters.
Also, I did not bother to deal with /
, since /
along with \0
are the only characters that are not allowed in filenames and you simply cannot create a file name that contains a /
.
rename
command. It issed
for filenames. (be careful, there are many programs with this name). – ctrl-alt-delor Oct 22 '20 at 16:38