rename all files in a directory to the md5 hash of their filename (not content)
You didn't say which shell you want to use, so I'm just assuming Bash – the answer needs adjustments to work with other shells.
for i in *; do sum=$(echo -n "$i"|md5sum); echo -- "$i" "${sum%% *}.${i##*.}"; done
Script version:
for i in *; do
sum=$(echo -n "$i" | md5sum)
echo -- "$i" "${sum%% *}.${i##*.}"
done
This simple for
loop takes every file in the current directory, computes the md5 sum of its name and outputs it. Use this to check the functionality, if you want to start renaming replace the second echo
by mv
.
Explanations
echo -n "$i" | md5sum
– calculate md5 sum of the full file name including the file extension (Piping), to strip the extension changeecho -n "$i"
to one of the following:${i%%.*} sed 's/\..*//' <<< "$i" echo "$i" | sed 's/\..*//'
sum=$(…)
– execute…
and save the output in$sum
(Command Substitution)${sum%% *}
– output everything until the first space (Parameter Substitution), the same as one of the following:$(sed 's/ .*//' <<< "$sum") $(echo "$sum" | sed 's/ .*//')
${i##*.}
– output everything after the last dot (Parameter Substitution), the same as one of the following:$(sed 's/.*\.//' <<< "$i") $(echo "$i" | sed 's/.*\.//')
If you need to rename files recursively in different folders, use find
with the -exec
option.
#!/bin/bash
md5name () {
local base=${1##*/}
local ext=${base##*.}
local dir=${1%/*}
printf '%s' "${base%.$ext}" | md5sum |
awk -v dir="$dir" -v ext="$ext" '{ printf("%s/%s.%s\n", dir, $1, ext) }'
}
dir=$HOME # where your files are
for pathname in "$dir"/*; do
test -f "$pathname" || continue
echo mv "$pathname" "$( md5name "$pathname" )"
done
This bash
script uses the md5sum
utility from GNU coreutils to compute the MD5 hash from the base name (sans extension) of any given pathname. The helper function md5name
does the actual computation and will output the new name with complete path and extension.
The md5name
function uses awk
to assemble the new name from the parts of the given pathname and the result from md5sum
.
Examples of the function in use by itself:
$ md5name '/some/path/file name here.extension'
/some/path/c9e89fa443d16da4b96ea858881320c9.extension
... where c9e89fa443d16da4b96ea858881320c9
is the MD5 hash of the string file name here
.
Remove the echo
from the script at the top to actually rename the files. You may want to save the output of the original script to file (with the echo
in place) if you at some point need to restore the file names to their originals.
Note that running this twice on a set of files will compute the MD5 hash of MD5 hashes, and that the original filename then becomes unrecoverable unless you make careful notes about what files are called what after each run of the script.
With perl
's rename
:
find . -name '*.jpg' -type f -exec rename -n '
BEGIN{use Digest::MD5 qw(md5_hex)}
my ($dir, $name, $ext) = m{(.*)/(.*)\.(.*)}s;
$_ = "$dir/" . md5_hex($name) . ".$ext"' {} +
(remove -n
when happy).