With find:
find . -type f -exec sh -c 'SHELL COMMAND' {} \;
This invokes SHELL COMMAND
on each found file in turn; the file name is "$0"
. Thus:
find . -type f -exec sh -c '
mv "$0" "${0%/*}/$(printf "%s\n" "${0##*/}" | sha1sum | cut -d" " -f1)"
' {} \;
(Note the use of printf
rather than echo
, in case you have a file called -e
or -n
or a few other problematic cases that echo
mangles.)
You can make this a little faster by invoking the shell in batches.
find . -type f -exec sh -c 'for x; do
mv "$x" "${x%/*}/$(printf "%s\n" "${x##*/}" | sha1sum | cut -d" " -f1)";
done' _ {} +
In zsh, there's an easy way to match all the files in the current directory and its subdirectories recursively. The .
glob qualifier restricts the matches to regular files, and D
includes dot files.
for x in **/*(.D); do mv …; done
In bash ≥4, you can run shopt -s globstar
and use **/*
to match all files in the current directory and its subdirectories recursively. You'll need to filter regular files in the loop.
shopt -s globstar; GLOBIGNORE=".:.."
for x in **/*; do if [[ -f $x ]]; then mv …; done
echo
will insert a newline at end of of output, so modifying the sha1sum output with respect to what you would expect for the bare string.