シェルから親ディレクトリの「basename」のみを抽出するにはどうすればよいですか?

シェルから親ディレクトリの「basename」のみを抽出するにはどうすればよいですか?

シェルスクリプトを使用して、特定の「キー」に複数のファイルの名前を変更する必要があります。キーは、文字列と.txtファイルを使用して取得したファイルパスの抽出部分で構成されていますfind

私はMac、OSX El Capitanを使用しており、ZSHを使用しています。ここにいるディレクトリツリー:

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

名前を変更する必要があります。../インデックス/フォルダ../c2_[親フォルダ名]/。これが私が試していることです:

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

basename残念ながら、これは親を救う正しい方法ではないようです。

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

これは単なるバリエーションであり、機能しません(動作する理由はありません:))。

私は初めてシェルスクリプトに触れて、できるだけ学びたいと思います。シェルとは何の関係もない片道なので、現在ZSHを使用していることを無視してください。

答え1

zsh使用するのが最善ですzmv:

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

(幸せなら削除-n)。

ポータブル(POSIXsh)解決策:

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

-i貧しい人の精神状態チェックに代わってzmv)。

使いたいならfind-mindepth移植可能(POSIXly)では、/を忘れなければならず、次の組み合わせ-maxdepthで置き換えることができます。-path-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 {} +

他の2つの方法との違いの1つは、シンボリックリンクに従わずに隠されたindexディレクトリも検索することです。

ここまたはサイトの多数のQ&Aで説明されている標準パラメータ拡張演算子を使用してください${var#pattern}${var%pattern}POSIXシェル仕様

答え2

それだけの価値があるだけ試してみてください。

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

ほとんど動作しているようですが、basename少し説明することはできません。しかし、dirname両親に与えなければならない名前を得れば、basenameその名前も得ることができます。このような:

$ mkdir -p 300x250/index 970x250/index
$ find . -name index -exec sh -c 'echo mv "$1" "$(dirname "$1")/C2_$(basename "$(dirname "$1")")"' sh {} \;
mv ./300x250/index ./300x250/C2_300x250
mv ./970x250/index ./970x250/C2_970x250

Stéphaneが述べたように、次の最初のパラメータはsh -c "..."スクリプト名として扱われ、上記で提供され、$0一般的な場所パラメータとは異なります$1。後者には、shiftおよびなど、これを処理するように特別に設計されたツールがありますが、$@処理することはできません$0

単一の引数に対しては using が$0機能しますが、シェル名が他の目的に使用される可能性があるため、shそこで合理的なものを設定してから(たとえば、実際の引数を後に置くことをお勧めします)。

答え3

働いたことがないZTEしかし、以下のコードは正常に実行されます。強く打つ

SHW@SHW:/tmp/test1 # 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

8 directories, 4 files

SHW@SHW:/tmp/test1 # for i in `find . -type d -name index`; do  mv $i `dirname $i | cut -c3-`/c2_`dirname $i | cut -c3-`; done

SHW@SHW:/tmp/test1 # tree
.
├── 300x250
│   ├── 300x250-img-fallback.jpg
│   └── c2_300x250
├── 300x600
│   ├── 300x600-img-fallback.jpg
│   └── c2_300x600
├── 336x280
│   ├── 336x280-img-fallback.jpg
│   └── c2_336x280
└── 970x250
    ├── 970x250-img-fallback.jpg
    └── c2_970x250

8 directories, 4 files

関連情報