Delete spaces, hyphens, and underscores in filenames?
The version of rename
that comes with the perl
package supports regular expressions:
rename "s/[-_ ]//g" *
Alternatively,
rename -i "s/[-_ ]//g" *
The -i
flag will make rename
use interactive mode, prompting if the target already exists, instead of silently overwriting.
Perl's rename is sometimes called prename
.
Perl's rename versus util-linux's rename
On Debian-like systems, perl's rename seems to be the default and the above commands should just work.
On some distributions, the rename
utility from util-linux is the default. This utility is completely incompatible with Perl's rename
.
All: First, check to see if Perl's
rename
is available under the nameprename
.Debian: Perl's rename should be the default. It is also available as
prename
. Therename
executable, though, is under the control of/etc/alternatives
and thus could have been altered to something different.archlinux: Run
pacman -S perl-rename
and the command is available asperl-rename
. For a more convenient name, create an alias. (Hat tip: ChiseledAbs)Mac OSX According to this answer,
rename
can be installed on OSX using homebrew via:brew install rename
Direct Download:
rename
is also available from Perl Monks:wget 'http://www.perlmonks.org/?displaytype=displaycode;node_id=303814' -O rename
I would replace all those tr
commands, with a sed
substitution command, e.g.:
for file in %N; do
mv "$file" "$(echo "$file" | sed 's/[ _-]//g')"
done
Not counting mv
, you don't really need an outside process for this at all - you can kind of just poof them.
ifsqz() ( LC_ALL=C sqz=$1
isf() { [ -e "$1" ] || [ -L "$1" ] ; }
set -- * ; set -f
for f do isf "$f" || break
IFS=$sqz; set -- $f; IFS=
isf "$*" || mv -- "$f" "$*"
done
)
Still though, that means a mv
invocation per file, and so probably rename
is better. Though this should work given only a POSIX mv
in $PATH
and a POSIX shell.
So, I came up with a kind of crazy demo for this. The test set is generated like:
tee - - - - <<CGEN |\
dd cbs=90 conv=unblock |\
sed 'G;$!N'";s/^/touch -- '/;s/$/'/" |sh
$( #BEGIN CGEN
LC_ALL=C
i= n='"$((i=((i=i+1)==10||i==39||i==47)>0?(i+1):i))"'
printf '%b -_ ---___' $(
IFS=0; eval \
printf '"\\\\%04o\\\\%04o "' "$(
printf "$n"' "$i" '%s $(
printf %.252d
#END
))"))
CGEN
In the first place I will be the first to acknowledge that the above command produces results that can be more easily obtained by other means. But other means would likely not demonstrate as well what might be done with $IFS
and a little (sick?) imagination.
So the first bit is fairly straight-forward:
tee
pipes out 5 copies of its input - the heredocument calledCGEN
dd
blocks its input by newlines at 90 bytes per block and pipes that to ...sed
joins 2 of those blocks on two\n
ewline characters,'
single-quotes the results, and prepends the stringtouch --
for every line cycle before piping out to ...sh
which then executes all input as shell commands
The #CGEN
bit though... Well, briefly...
the bottom
printf
prints 252 0sthe next from last receives 252
''
null-string arguments and for each prints the contents of$n
followed by the string" $i "
eval
interprets the arguments of the next upprintf
before it prints the results of that interpretation as octal nums prepended by 2 backslashes a piecethe last
printf
prints the byte values for those octals 2 at a time followed by the string-_ ---___
for each pair$n
is initialized to an equation that will increment$i
by one for every evaluation excepting that it skips the values 10, 39, or 47 - (which are\n
ewline,'
single-quote, and/
slash in ASCII decimal respectively)
The end result is a directory containing a lot of really ugly filenames containing every byte in my charset from 1 through 255 excepting the single-quote (only skipped to avoid one more sed s///
statement) and the /
slash. Those filenames look like this:
(set -- *; printf '%s\n\n##############\n\n%s\n' "${9}" "${34}") | cat -A
---___ww -_ ---___xx -_ ---___yy -_ ---___zz -_ ---___{{ -_ ---___|| -_ ---$
$
___}} -_ ---___~~ -_ ---___^?^? -_ ---___M-^@M-^@ -_ ---___M-^AM-^A -_ ---___M-^BM-^B -_ ---___M-^CM-^C$
$
##############$
$
-_ ---___M-ZM-Z -_ ---___M-[M-[ -_ ---___M-\M-\ -_ ---___M-]M-] -_ ---___M-^M-^ -_ ---___M-_M-_ -_$
$
---___M-`M-` -_ ---___M-aM-a -_ ---___M-bM-b -_ ---___M-cM-c -_ ---___M-dM-d -_ ---___M-eM-e -_ ---___$
Now I'll get some data on these files:
chksqz() ( LC_ALL=C sqz=$1
set -- * ; set -f ; IFS= ; tc="$*"
printf '#%s\n' \
"There are $# files in this test directory." \
"All filenames combined contain a total of ${#tc} bytes."
IFS=$sqz ; set -- $* ; IFS= ; sc="$*"
printf "%s '$sqz'" \
"#Of which ${#sc} bytes are not"\
" and $((${#tc}-${#sc})) bytes are"
set +f ; unset IFS
printf ".\n#%s\n#Total:\t%d\n#Other:\t%d\n#'$sqz':\t%d\n" \
"And to confirm these figures:" \
$( printf %s * | wc -c
printf %s * | tr -d "$sqz" | wc -c
printf %s * | tr -dc "$sqz" | wc -c
))
chksqz '_ -'
OUTPUT
#There are 101 files in this test directory.
#All filenames combined contain a total of 17744 bytes.
#Of which 2692 bytes are not '_ -' and 15052 bytes are '_ -'.
#And to confirm these figures:
#Total: 17744
#Other: 2692
#'_ -': 15052
Ok. Now finally, to action:
ifsqz '_ -'
chksqz '_ -'
OUTPUT
#There are 101 files in this test directory.
#All filenames combined contain a total of 2692 bytes.
#Of which 2692 bytes are not '_ -' and 0 bytes are '_ -'.
#And to confirm these figures:
#Total: 2692
#Other: 2692
#'_ -': 0
Success! You can see for yourself:
ls
????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
???????????????????????????
???????????????????????????
???????????????????????????
????????????????????????????
????????????????????????????
????????????????
??????????????????????
????????????????????????
??????????????????????????
??????????????????????????
??????????????????????????
??????????????????????????
???????????????????????????
???????????????????????????
???????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
??????????????????????????
????????????????????????
????????????????????
??????????????????
????????????????????????????
??
????????????????????????????
??????????????????????????
????????????????????????????
????????????????????????????
????????????????????!!""##
??????????????????!!""##$$
????????????????!!""##$$%%
????????????!!""##$$%%&&((
????????!!""??##$$%%&&(())
$$%%&&(())**??++,,..0011
%%&&(())**++??,,..00112233
&&(())**++,,??..0011223344
))**++,,..??0011223344556
**++,,..00??11223344556677
22334455667788??99::;;<<==>>
445566778899??::;;<<==>>??@@
5566778899::;;??<<==>>??@@AA
6778899::;;<<??==>>??@@AABB
8899::;;<<==??>>??@@AABBCCDD
\\]]^^``aa??bbccddeeffgghh
]]^^``aabbc??cddeeffgghhii
^^``aabbccdd??eeffgghhiijj
??@@AABBCCDDEE??FFGGHHIIJJKK
AABBCCDDEEFF??GGHHIIJJKKLLM
BBCCDDEEFFGG??HHIIJJKKLLMMNN
CCDDEEFFGGHHII??JJKKLLMMNNOO
EEFFGGHHIIJJ??KKLLMMNNOOPPQQ
ffgghhiijjkk??llmmnnooppqqrr
gghhiijjkkllmm??nnooppqqrrss
iijjkkllmmnn??ooppqqrrsstt
jjkkllmmnnoo??ppqqrrssttuuvv
kkllmmnnooppqq??rrssttuuvvww
LLMMNNOOPPQQRR??SSTTUUVVWWXX
MNNOOPPQQRRSS??TTUUVVWWXXYY
OOPPQQRRSSTT??UUVVWWXXYYZZ[[
PPQQRRSSTTUUVV??WWXXYYZZ[[\\
RRSSTTUUVVWW??XXYYZZ[[\\]]
ssttuuvvwwxx??yyzz{{||}}~~??
ttuuvvwwxxyyz??z{{||}}~~????
uuvvwwxxyyzz{{??||}}~~??????
wwxxyyzz{{||??}}~~??????????
xxyyzz{{||}}~~??????????????
YYZZ[[\\]]^^??``aabbccddee
ZZ[[\\]]^^``??aabbccddeeff