1

I have a bunch of video files where all the file names are un-useful gibberish.

1) Is there an easy command to change the names of all the files in a folder to a hash, like (sha256).mp4? I don't want to move / copy / modify any files, only rename them.

2) Can the command from 1) be modified to only add the hash onto the end of the original file name? Like (original name)_(sha256).mp4

I'm quite new to Ubuntu/Linux and would greatly appreciate an explanation for what each part of the command does.

dessert
  • 39,392
  • 12
  • 115
  • 163
Yamashita
  • 11
  • 1
  • 3
  • Any command you can come up with to do it ONCE you can put a loop around to have it repeat it on a next file so the answer is yes. There is a command "rename" and a command "rename.ul" in linux to rename files. It does accept regexes and the normal variables to change a filename – Rinzwind Mar 01 '19 at 15:02

4 Answers4

2

You can actually do this with this rename command:

rename 'chomp(my $new=`sha256sum "$_" | cut -d" " -f1`); s/.*/$new.mp4/' *mp4

To preview what it will do before actually renaming, use -n. For example:

$ ls
'my movie file01.mp4'  'my movie file05.mp4'  'my movie file09.mp4'
'my movie file02.mp4'  'my movie file06.mp4'  'my movie file10.mp4'
'my movie file03.mp4'  'my movie file07.mp4'
'my movie file04.mp4'  'my movie file08.mp4'

$ rename -n 'chomp(my $new=`sha256sum "$_" | cut -d" " -f1`); s/.*/$new.mp4/' *mp4
my movie file01.mp4 -> 6a260f4adeb47000afeb9c53029ce0e14b6ea80be5c649ecdb155c8e7cfa1496.mp4
my movie file02.mp4 -> 14f24228ead10d639ef3db11ea09c6216aa80879327a2a57fb549e6474fb05b0.mp4
my movie file03.mp4 -> 6c9ecec6a75e217fa1786dd6f920a5c1db8473f17447595e0d33d7fc3530453a.mp4
my movie file04.mp4 -> 96a29ae5bc3a5e35537bcea1068c746ddba205d17fcc8e522a52402c7ed69927.mp4
my movie file05.mp4 -> 189207823129b57e52c86a743ea7154f65b8eccb5182f322abc3aae35f14057d.mp4
my movie file06.mp4 -> 93be0fd15be56bb22af94a0a0aa272d56f61e77160f1170305d41166d6135913.mp4
my movie file07.mp4 -> 05c92b5632414f14445af3facdb0e187746b3b0f40bad94a5f351aeb7f9a8847.mp4
my movie file08.mp4 -> 0d3cf9c165d4c18af8922b8daa9a6b1031c6762d179fb910b968d60af9aed255.mp4
my movie file09.mp4 -> da04afebaec6ea3d43dc3a0e66b790ab13751b00fd81aa1f882986c097c36298.mp4
my movie file10.mp4 -> 47bf532970d3e759346462a85d15ab9d9171c5a7688a6e90a1e976e071ecd167.mp4

And, to keep the original name:

$ rename -n 'chomp(my $new=`sha256sum "$_" | cut -d" " -f1`); s/.*/$_ $new.mp4/' *mp4
my movie file01.mp4 -> my movie file01.mp4 6a260f4adeb47000afeb9c53029ce0e14b6ea80be5c649ecdb155c8e7cfa1496.mp4
my movie file02.mp4 -> my movie file02.mp4 14f24228ead10d639ef3db11ea09c6216aa80879327a2a57fb549e6474fb05b0.mp4
my movie file03.mp4 -> my movie file03.mp4 6c9ecec6a75e217fa1786dd6f920a5c1db8473f17447595e0d33d7fc3530453a.mp4
my movie file04.mp4 -> my movie file04.mp4 96a29ae5bc3a5e35537bcea1068c746ddba205d17fcc8e522a52402c7ed69927.mp4
my movie file05.mp4 -> my movie file05.mp4 189207823129b57e52c86a743ea7154f65b8eccb5182f322abc3aae35f14057d.mp4
my movie file06.mp4 -> my movie file06.mp4 93be0fd15be56bb22af94a0a0aa272d56f61e77160f1170305d41166d6135913.mp4
my movie file07.mp4 -> my movie file07.mp4 05c92b5632414f14445af3facdb0e187746b3b0f40bad94a5f351aeb7f9a8847.mp4
my movie file08.mp4 -> my movie file08.mp4 0d3cf9c165d4c18af8922b8daa9a6b1031c6762d179fb910b968d60af9aed255.mp4
my movie file09.mp4 -> my movie file09.mp4 da04afebaec6ea3d43dc3a0e66b790ab13751b00fd81aa1f882986c097c36298.mp4
my movie file10.mp4 -> my movie file10.mp4 47bf532970d3e759346462a85d15ab9d9171c5a7688a6e90a1e976e071ecd167.mp4

The explanation here is a bit complicated as it requires understanding some basic Perl. The main idea is:

  • my $new=`sha256sum "$_" | cut -d" " -f1` : this will run the command sha256sum on each input file ($_ is Perl magic for "current thing"), and cut to keep only the hash. To illustrate:

    $ sha256sum my\ movie\ file01.mp4 
    6a260f4adeb47000afeb9c53029ce0e14b6ea80be5c649ecdb155c8e7cfa1496  my movie file01.mp4
    $ sha256sum my\ movie\ file01.mp4 | cut -d" " -f1
    6a260f4adeb47000afeb9c53029ce0e14b6ea80be5c649ecdb155c8e7cfa1496
    

    The chomp() just removes the trailing newline from the command's output. The result is stored in the variable $new.

  • s/.*/$new.mp4/' : substitute everything (.*) with the $new name.

Or, for the other command:

  • s/.*/$_ $new.mp4/' : substitute everything with the original name ($_) followed by the new one.
terdon
  • 98,183
  • 15
  • 197
  • 293
  • does not work. rename -n 'chomp($new=`sha256sum "$_" | cut -d" " -f1`); s/.*/$_ $new.mp4/' *mp4 Global symbol "$new" requires explicit package name (did you forget to declare "my $new"?) at (user-supplied code). – Vijay Mar 01 '19 at 17:55
  • @VeeJay wow, Ubuntu seems to have changed `rename` so that it runs with `use strict`! How strange. Thanks for the heads up, see updated answer. – terdon Mar 01 '19 at 18:07
1

Tried and tested. For file names with spaces also.

1)

find . -maxdepth 1 -name '*.mp4' -print0 | while read -d $'\0' i ;do
    mv "$i" "`sha256sum "$i" | cut -d" " -f1`.mp4"
done

2)

find . -maxdepth 1 -name '*.mp4' -print0 | while read -d $'\0' i ;do
    mv "$i" "${i%%.mp4}-`sha256sum "$i" | cut -d" " -f1`.mp4"
done
Vijay
  • 7,606
  • 3
  • 17
  • 34
0

I just wanted to share my improvements on Vijay's answer

If you want to make this process recursive (includes all sub-directories) you can use following command:

find . -name '*.mp4' -print0 | while read -rd $'\0' i; do
  mv -v "$i" "$(dirname "$i")/$(sha256sum "$i" | cut -d" " -f1).mp4"
done
asandikci
  • 71
  • 7
-2

This needs a simple shell loop:

for i in *.mp4 ; do
    j="$(openssl dgst -sha256 \"$i\" | cut '-d ' -f2)"
    mv "$i" "$j.mp4"
done

The 2nd part of your question needs a little more work:

for i in *.mp4 ; do
    j="$(openssl dgst -sha256 \"$i\" | cut '-d ' -f2)"
    k="${i%%.mp4}"
    mv "$i" "$k_$j.mp4"
done
Kulfy
  • 17,416
  • 26
  • 64
  • 103
waltinator
  • 35,099
  • 19
  • 57
  • 93