シェル スクリプト: ファイル パスの一部をファイル名として使用するにはどうすればよいでしょうか?

シェル スクリプト: ファイル パスの一部をファイル名として使用するにはどうすればよいでしょうか?

次のように、それぞれに 1 つの jpeg 画像が含まれるディレクトリのグループがあります。

/psds/folder1/image.jpg
/psds/someotherfolder/picture.jpg
/psds/yetanotherfolder/thumbnail.jpg

jpeg の名前を、それが含まれているフォルダの名前に変更する適切な方法は何ですか? 私が望んでいるのは次のとおりです:

/psds/folder1/folder1.jpg
/psds/someotherfolder/someotherfolder.jpg
/psds/yetanotherfolder/yetanotherfolder.jpg

答え1

/psdsディレクトリ内で以下のコマンドを実行します。

for f in ./*; do
    if [ -d "$f" ] ; then
        cd "$f"
        mv *.jpg "$f.jpg"
        cd ..
    fi
done

/psds以下のようにディレクトリ内に3つのフォルダがある場合、

/psds/folder1/image1.jpg
/psds/folder2/image2.jpg
/psds/folder3/image3.jpg

上記のコマンドを実行すると、ファイル名は次のように変更されます。

/psds/folder1/folder1.jpg
/psds/folder2/folder2.jpg
/psds/folder3/folder3.jpg

答え2

あなたはシェルパラメータの拡張${VAR#PREFIX}および構造${VAR%SUFFIX}を使用して、指定されたプレフィックスまたはサフィックスを取り除いた変数の値を取得します。 PREFIX がパターンの場合、最短の一致文字列が削除されます。 または の場合は##%%最長の一致が削除されます。 これらの構造は、bash だけでなく、すべての sh タイプ (Bourne/POSIX) シェルで使用できます。

の値がVARのようなパスである場合/path/to/directory/file、 は"${VAR%/*}"ファイルを含むディレクトリであり、"${VAR##*/}"はディレクトリ部分を除いたファイル名です。"${VAR%/*}"が正しいのは、 に$VAR少なくとも 1 つの が含まれる場合のみ/、およびが で終わらない"${VAR##*/}"場合のみであることに注意してください。 および と呼ばれるユーティリティもあり、この点ではより信頼性があります。 同様に、は最後の拡張子です。VAR/dirnamebasename${VAR##*.}

for x in /psds/*/*.jpg; do
  dir="${x%/*}"
  mv "$x" "$dir/${dir##*/}.jpg"
done

いつものように、zshは少し難解ですが、短くてわかりやすい方法です。zmv関数は、大量のファイルの名前を変更するのに便利です。

autoload -U zmv   # put this in your .zshrc
zmv '/psds/(*)/*.jpg' '/psds/$1/$1.jpg'

別のアプローチとしては、履歴拡張修飾子パラメータ拡張について:

zmv '/psds/*/*.jpg' '$f:h/$f:h:t.$f:e'

関連情報