Rename files to md5 sum + extension (BASH)
This might work for you:
# mkdir temp && cd temp && touch file.{a..e}
# ls
file.a file.b file.c file.d file.e
# md5sum * | sed -e 's/\([^ ]*\) \(.*\(\..*\)\)$/mv -v \2 \1\3/' | sh
`file.a' -> `d41d8cd98f00b204e9800998ecf8427e.a'
`file.b' -> `d41d8cd98f00b204e9800998ecf8427e.b'
`file.c' -> `d41d8cd98f00b204e9800998ecf8427e.c'
`file.d' -> `d41d8cd98f00b204e9800998ecf8427e.d'
`file.e' -> `d41d8cd98f00b204e9800998ecf8427e.e'
Or GNU sed can do it even shorter:
# md5sum * | sed -e 's/\([^ ]*\) \(.*\(\..*\)\)$/mv -v \2 \1\3/e'
Rename files to hash and extension
I find this easier to read and follow:
#!/bin/bash
source_dir=/home/hermit/Documents/Pictures
destination_dir=/home/hermit/Documents/HashPictures
for file in "${source_dir}"/*;do
hash=$(md5sum "${file}"|cut -d' ' -f1)
ext=${file##*.}
cp -v "$file" "${destination_dir}/${hash}.${ext}"
done
How to rename files inside folder to its corresponding md5sum?
See Why you shouldn't parse the output of
ls
orfind
in a for-loop, ParsingLs,
If you have file names with spaces also
recommend using -print0
option of GNU findutils
for the job which embeds a \0
character after file name with read
with a null delimiter as below.
Run the script below inside /home/SomeFolder
and use find from the current directory as
#!/bin/bash
while IFS= read -r -d '' file
do
mv -v "$file" "$(md5sum $file | cut -d ' ' -f 1)"
done< <(find . -mindepth 1 -maxdepth 1 -type f -print0)
The depth options ensure the current folder .
is not included in the search result. This will now get all the files in your current directory ( remember it does not recurse through sub-directories) and renames your file with the md5sum
of the filenames.
The -v
flag in mv
is for verbose output ( which you can remove) for seeing how the files are to be renamed as.
Replace the complete filenames for files with their MD5 hash string of the content in bash
Make things simple by making use the glob patterns that the shell provides, instead of using external utilities like find
. Also see Why you don't read lines with "for"
Navigate inside the folder /home/admin/test
and do the following which should be sufficient
for file in *; do
[ -f "$file" ] || continue
md5sum -- "$file" | { read sum _; mv "$file" "$sum"; }
done
Try using echo
inplace of mv
first to check once if they files are renamed as expected.
To go to sub-directories below, which I assume would also be your requirement, enable globstar
, which is one of the extended globing options provided by the shell to go deeper
shopt -s globstar
for file in **/*; do
Rename files to CRC32 and extension
Here is a step by step explanation:
$ ls -1
abc.txt
def.txt
ghi.txt
$ crc32 *
c7e06c1a abc.txt
042999b4 def.txt
e686c130 ghi.txt
$ crc32 * | sed -e "s/^\(\S*\)\s*\(.*\(\..*\)\)$/mv -v \2 \1\3/g"
mv -v abc.txt c7e06c1a.txt
mv -v def.txt 042999b4.txt
mv -v ghi.txt e686c130.txt
what happens in detail:
s/ # substitute the following expression
^ # begin of line
\(\S*\) # store every char until whitespace (\1)
\s* # whitespace
\(.* # store every char... (\2)
\(\..*\) # until '.', store it extra (\3)
\) # end brace of \2
$ # end of line
/mv -v \2 \1\3 # command with stored arguments
/g # global, on the whole line
to perform in one step, replace the "g" with an "e"
$ crc32 * | sed -e "s/^\(\S*\)\s*\(.*\(\..*\)\)$/mv -v \2 \1\3/e"
renamed 'abc.txt' -> 'c7e06c1a.txt'
renamed 'def.txt' -> '042999b4.txt'
renamed 'ghi.txt' -> 'e686c130.txt'
if you are not using gnu sed, remove "e" and add "| sh"
crc32 * | sed -e "s/^\(\S*\)\s*\(.*\(\..*\)\)$/mv -v \2 \1\3/" | sh
Will changing a file name affect the MD5 Hash of a file?
The usual definition of "MD5 hash of a file" is that the hash is based on the file contents. The name can be freely changed.
$hash1 = md5(file);
// change file name
$hash2 = md5(file);
The two hash codes will be the same.
In some (fairly specialized) use cases, file metadata (name, time stamp(s), etc.) are part of the data used to compute the hash. Then
$hash1 = md5(file);
// change file name
$hash2 = md5(file);
will produce two separate hashes.
How to rename files with output from program in bash?
You can reuse the answer from: Rename files to md5 sum + extension (BASH)
By modifying a little bit it will do exactly what you want (I already edited the command for you):
md5sum * | sed -e 's/\([^ ]*\) \(.*\)$/mv -v "\2" \1/' | sh
Example of output:
'a' -> 'b026324c6904b2a9cb4b88d6d61c81d1'
'b' -> '26ab0db90d72e28ad0ba1e22ee510510'
'c' -> '6d7fce9fee471194aa8b5b6e47267f03'
Rename files to md5 sum + extension on Windows 7 (with CMD or PowerShell 2013)
You didn't write what you've already got, so I won't explain the script. Just remember that you'll get an error for files with same md5.
Get-ChildItem d:\temp\*.xxx | select FullName, Extension, @{name='md5'; expression={(Get-FileHash $_ -Algorithm md5).Hash}} | foreach {Rename-Item $_.FullName -NewName "$($_.md5)$($_.extension)"}
Related Topics
How to Extract Characters Between the Delimiters Using Sed
How to Create a File in Linux from Terminal Window
Attach to a Processes Output for Viewing
Fastest Way to Tell If Two Files Have the Same Contents in Unix/Linux
Ssh: Could Not Resolve Hostname [Hostname]: Nodename Nor Servname Provided, or Not Known
Copy Folder Structure (Without Files) from One Location to Another
Tilde Expansion in Environment Variable
Linux Kernel System Call Returns -1 Instead of {-1, -256}
The Irq in Kernel Function Asm_Do_Irq() Is Different from the One I Request in Module
Moving Multiple Files Having Spaces in Name (Linux)
Differencebetween './Example.Sh' and 'Sh Example.Sh'
How to Look Up a Variable by Name with #!/Bin/Sh (Posix Sh)
Fast Concatenate Multiple Files on Linux
Gzip Multiple Files Individually and Keep the Original Files
Using Linux How to Pass the Contents of a File as a Parameter to an Executable