Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><strong>Updated to fix:<br></strong> 1. File names with '[' or ']' in their name (really, any character now. See comment)<br> 2. Handling of md5sum when hashing a file with a backslash or newline in its name<br> 3. Functionized hash-checking algo for modularity<br> 4. Refactored hash-checking logic to remove double-negatives<br></p> <pre><code>#!/bin/bash if (($# != 1)) || ! [[ -d "$1" ]]; then echo "Usage: $0 /path/to/directory" exit 1 fi is_hash() { md5=${1##*.} # strip prefix [[ "$md5" == *[^[:xdigit:]]* || ${#md5} -lt 32 ]] &amp;&amp; echo "$1" || echo "${1%.*}" } while IFS= read -r -d $'\0' file; do read hash junk &lt; &lt;(md5sum "$file") basename="${file##*/}" dirname="${file%/*}" pre_ext="${basename%.*}" ext="${basename:${#pre_ext}}" # File already hashed? pre_ext=$(is_hash "$pre_ext") ext=$(is_hash "$ext") mv "$file" "${dirname}/${pre_ext}.${hash}${ext}" 2&gt; /dev/null done &lt; &lt;(find "$1" -path "*/.*" -prune -o \( -type f -print0 \)) </code></pre> <p>This code has the following benefits over other entries thus far</p> <ul> <li><strong>It is fully compliant with Bash versions 2.0.2 and beyond</strong></li> <li>No superfluous calls to other binaries like sed or grep; uses builtin parameter expansion instead</li> <li>Uses process substitution for 'find' instead of a pipe, no sub-shell is made this way</li> <li>Takes the directory to work on as an argument and does a sanity check on it</li> <li>Uses $() rather than `` notation for command substitution, the latter is deprecated</li> <li>Works with files with spaces</li> <li>Works with files with newlines</li> <li>Works with files with multiple extensions</li> <li><strong>Works with files with no extension</strong></li> <li>Does not traverse hidden directories</li> <li><strong>Does <em>NOT</em> skip pre-hashed files, it will recalculate the hash as per the spec</strong></li> </ul> <h3>Test Tree</h3> <pre> $ tree -a a a |-- .hidden_dir | `-- foo |-- b | `-- c.d | |-- f | |-- g.5236b1ab46088005ed3554940390c8a7.ext | |-- h.d41d8cd98f00b204e9800998ecf8427e | |-- i.ext1.5236b1ab46088005ed3554940390c8a7.ext2 | `-- j.ext1.ext2 |-- c.ext^Mnewline | |-- f | `-- g.with[or].ext `-- f^Jnewline.ext 4 directories, 9 files </pre> <h3>Result</h3> <pre> $ tree -a a a |-- .hidden_dir | `-- foo |-- b | `-- c.d | |-- f.d41d8cd98f00b204e9800998ecf8427e | |-- g.d41d8cd98f00b204e9800998ecf8427e.ext | |-- h.d41d8cd98f00b204e9800998ecf8427e | |-- i.ext1.d41d8cd98f00b204e9800998ecf8427e.ext2 | `-- j.ext1.d41d8cd98f00b204e9800998ecf8427e.ext2 |-- c.ext^Mnewline | |-- f.d41d8cd98f00b204e9800998ecf8427e | `-- g.with[or].d41d8cd98f00b204e9800998ecf8427e.ext `-- f^Jnewline.d3b07384d113edec49eaa6238ad5ff00.ext 4 directories, 9 files </pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload