Shell – How to Extract Basename of Parent Directory

findmvshellzsh

I need to rename a couple of files using shell scripting, by a certain "key". This key includes both strings as well as extracted portions of file path that I get with find.

I am on a Mac, OSX El Capitan and am using ZSH. Here is the directory tree:

├── 300x250
│   ├── 300x250-img-fallback.jpg
│   └── index/
├── 300x600
│   ├── 300x600-img-fallback.jpg
│   └── index/
├── 336x280
│   ├── 336x280-img-fallback.jpg
│   └── index/
└── 970x250
    ├── 970x250-img-fallback.jpg
    └── index/

I need to rename ../index/ folders into ../c2_[parentFolderName]/. This is what I am trying:

find . -type d -mindepth 2 -maxdepth 2 -exec sh -c 'echo -- mv "$0" "$(dirname "$0")"/"C2_"$(basename "$0/..")""' {} \;

This doesn't seem to be the proper way to get the basename of the parent unfortunately.

find . -name "*index" -exec sh -c 'echo -- mv "$0" "$(dirname "$0")"/"C2_"$(basename "$0/..")""' {} \;

This one is just a variation which also does not work (there is no reason why it should 🙂 ).

I am quite new to shell scripting and am trying to learn as much as possible in a shell agnostic kind of way, so please disregard that I am using ZSH currently.

Best Answer

Best would be to use zsh's zmv:

autoload zmv # best in ~/.zshrc
zmv -n '(*)/index' '$1/C2_$1'

(remove -n when happy).

For a portable (POSIX sh) solution:

for dir in */index;  do
  mv -i -- "$dir" "${dir%/*}/C2_${dir%/*}"
done

(using -i as a poor man's ersatz to the sanity checks zmv does).

If you wanted to use find portably (POSIXly), you'd need to forget about -mindepth/-maxdepth, which you can replace with combinations of -path and -prune:

LC_ALL=C find . -path './*/*' -prune -name index -exec sh -c '
  for dir do
    top=${dir#./}
    top=${top%/*}
    mv -i -- "$dir" "$top/C2_$top"
  done' sh {} +

One difference with the other two approaches is that it will not follow symlinks and that it will also look for index in hidden directories.

Those make use of the standard ${var#pattern}, ${var%pattern} parameter expansion operators described in countless Q&As here or at the POSIX shell specification.

Related Question