Siya Mzam
Siya Mzam

Reputation: 4705

Rename all files in directory and (deeply nested) sub-directories

What is the shell command for renaming all files in a directory and sub-directory (recursively)?

I would like to add an underscore to all the files ending with *scss from filename.scss to _filename.scss in all the directories and sub-directories.

I have found answers relating to this but most if not all require you to know the filename itself, and I do not want this because the filenames differ and are a lot to know by heart or even type them manually and some of them are deeply nested in directories.

Upvotes: 0

Views: 430

Answers (4)

Bastian Bittorf
Bastian Bittorf

Reputation: 507

#!/bin/sh

EXTENSION='.scss'
cd YOURDIR

find . -type f | while read -r LINE; do
  FILE="$( basename "$LINE" )"

  case "$LINE" in
    *"$EXTENSION")
      DIRNAME="$( dirname "$LINE" )"
      mv -v "$DIRNAME/$FILE" "$DIRNAME/_$FILE"
    ;;
  esac
done

Upvotes: 0

DevSolar
DevSolar

Reputation: 70263

Edit: I was under the impression that the bash -c bit was somehow necessary for multiple expansion of the found element; anubhava's answer proved me wrong. I am leaving that bit in the answer for now as it worked for the OP.

find . -type f -name *scss -exec bash -c 'mv $1 _$1' -- {} \;
  • find . -- find in current directory (recursively)
  • -type f -- files
  • -name *scss -- matching the pattern *scss
  • -exec -- execute for each element found
  • bash -c '...' -- execute command in a subshell
  • -- -- end option parsing
  • {} -- expands to the name of the element found (which becomes the positional parameter for the bash -c command)
  • \; -- end the -exec command

Upvotes: 2

Poshi
Poshi

Reputation: 5762

You are close to a solution:

find ./src/components -iname "*.scss" -print0 | xargs -0 -n 1 -I{} mv {} _{}

In this approach, the "loop" is executed by xargs. I prefer this solution overt the usage of the -exec in find. The syntax is clear to me.

Also, if you want to repeat the command and avoid double-adding the underscore to the already processed files, use a regexp to get only the files not yet processed:

find ./src/components -iregex ".*/[^_][^/]*\.scss" -print0 | xargs -0 -n 1 -I{} mv {} _{}

By adding the -print0/-0 options, you also avoid problems with whitespaces.

Upvotes: 1

anubhava
anubhava

Reputation: 785156

You can use -execdir option here:

find ./src/components -iname "*.scss" -execdir mv {} _{} \;

Upvotes: 1

Related Questions