Notes and References
find . -depth -name '*_*' -execdir bash -c 'for f; do mv "$f" "${f//_/-}"; done' bash {} +
This command uses a for
loop within the execdir
option to iterate over the files and directories found by find
and performs the renaming using the mv
command.
Here’s a breakdown of the command:
find .
: Searches for files and directories in the current directory and its subdirectories.-depth
: Processes the directory contents before the directory itself.-name '*_*'
: Specifies the pattern for filenames and directory names containing underscores.-execdir bash -c 'for f; do mv "$f" "${f//_/-}"; done' _whatever_ {} +
: For each batch of files or directories found, it executes a bash command that uses a for
loop to iterate over the items and rename them using the mv
command.
_whatever_
is needed because without it bash
with the -c
option will ignore the first result of the find
command in {}
.man
page for bash
:
-c string
If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0.
-c
flag in bash
will execute the command string with the parameters starting from $1
and not $0
, as $0
is the name of the script and not the file-paths being sent to the bash
'<command string>'
.$0
parameter with a dummy argument. It is typically set to bash
or _
for clarity.find . -name '*.md' -execdir bash -c 'echo "$@"' _ {} +
find . -name '*.md' -execdir bash -c 'echo "$0"' _ {} +
find . -name '*.md' -execdir bash -c 'echo "$@"' {} +
find . -name '*.md' -execdir bash -c 'echo "$1"' _ {} +
find . -name '*.md' -execdir bash -c 'echo "$1"' {} +
See this stackoverflow answer and another stackoverflow answer for further clarification.