この質問は私の別の質問から来ました。ここ(「シェルから親ディレクトリのベース名を抽出する方法))、これは「ウサギの穴」を開くようです。Unix文字列操作私のため。それでは、次は補足の質問です。
dirname
結果からさまざまな部分(「レベル」)を抽出する正しい方法は何ですかfind
?
次のような階層があるとしましょう。
DE_AT/adventure/motovun/300x250/A2_300x250.zip
次のようにファイルを「検索」します。
find . -name "*.zip"
シェル結果の実行find
:
-exec sh -c '' {} \;
フルパスの各部分をどのように抽出しますか?入手方法:
- DE_AT
- 冒険
- モトブン
- 300×250
- A2_300x250.zip
私が今まで知っているのは次のとおりです。
basename "$1" # gets me: A2_300x250.zip
dirname "$1" # gets me: ./DE_AT/adventure/motovun/300x250
この.zipファイルの名前を次のように変更する必要があるため、これを尋ねることです。someString_DE_AT_motovun+A2_300x250.zip。
私は次のような恐ろしいFrankenソリューションを思いついた。
find . -name "*.zip" -exec sh -c '
mv "$0" "myString_$(basename $(dirname $(dirname \
$(dirname "$0")_...+$(basename "$0")"
' {} \;
これが正しい方法がないので、私はこれを試したくありません。
ベストアンサー1
演算子を使用できますsplit+glob
。
find . -name '*.zip' -exec sh -c '
IFS=/ # split on /
set -f # disable glob
for file do
set -- $file # invoke split+glob, store in positional parameters
# now the path components are in $1, $2...
mv -i -- "$file" "someString_${2}_${4}+${6}"
done' sh {} +
$1
あるでしょう.
。$2
DE_AT
ちょっと待ってください。最後のパラメータを取得するには、次のようなものが必要なため、難しくなります。
eval "last=\${$#}"
zsh
たとえば、適切な分割演算子と配列を使用して他のシェルを使用する方が簡単です。
find . -name '*.zip' -exec zsh -c '
for file do
components=(${(s:/:)file})
printf "Last component: %s\n" $components[-1]
mv -i -- "$file" "someString_$components[2]_$components[-3]+$components[-1]"
done' zsh {} +
これにより、zsh
以下を使用することもできます。zmv
バッチの名前変更ツール:
autoload zmv # best in ~/.zshrc
zmv -n '([^/]#)/**/(*)/*/(*.zip)' 'someString_${1}_${2}+$3'
このセクションはすべてのレベル(レベル0を含む)のサブディレクトリと一致するため、置換のために**/
//に入るキャプチャ文字列(//、//)と一致して、上記の配列メソッドと同様の動作を提供します。(a)/b/c/(d)/e/(f.zip)
(a)/(b)/c/(d.zip)
a
d
f.zip
a
b
d.zip
$1
$2
$3
$components
その[^/]#
うちのいくつかは、/以外のすべてのシーケンスに一致する#
正規表現演算子と同じです。*
globの場合は、aを拡張できないのと同じように機能します*
が、globを拡張した後、結果ファイルからパターンマッチングを使用して置き換える部分を抽出し、代わりにあまりにも多くの部分に一致するようにaを拡張します。*
/
zmv
*
/
(*)
([^/]#)