
次のようなこの投稿注: エラーなしでfind
and コマンドを実行できますが、ファイル名は同じままです。sed
服を脱がせようとしていますの発音_de_現在のディレクトリのすべてのmp3:
pronunciation_de_wählen.mp3
pronunciation_de_wange.mp3
pronunciation_de_weil.mp3
pronunciation_de_werden.mp3
pronunciation_de_zentrum.mp3
コマンドの問題を解決する前にクイックステータスチェック:
find . -name "*.mp3"
現在のディレクトリのすべてのmp3を返します。これでこの部分がうまくいくことがわかりました。
sed --version
返品sed (GNU sed) 4.4
私は走るfind . -name "*.mp3" -exec sed -i 's/pronunciation_de_//g' {} \;
何が起こっているのか完全に理解していることを確認するには、次の手順を実行します。
find .
走る探す現在のディレクトリのコマンドです。
-name "*.mp3"
すべての.mp3ファイル形式を返します。
-exec
入力してコマンドを実行します。
sed -i
これ-私遷移とは、(一時的な)コピーではなく、実際のファイルで作業することを意味します。
のため's/old_word/new_word/g'
:
- これSsedを代替モードに設定します。
- /古い単語交換したい言葉です。
- /新しい単語交換したい言葉です。私の例では空です。
- / G最初の一致だけでなく、すべての一致に置換を適用します。
{}
この文字列は、各反復中にファイル名に置き換えられます。
\;
セミコロン終了探す注文する。バックスラッシュはセミコロン文字をエスケープし、シェルが文字通り解釈するのを防ぎます。
私はこの情報のほとんどをランダムなブログとStack Exchangeの投稿から入手します。
-exec オプションについてfind
findの-execコマンドで{} +はどういう意味ですか?
ほぼ確実に重複するこの質問を投稿する前に、時間をかけて実験して調査したいのですが、完全に詰まっています!
答え1
find -exec ...
1行のシェルスクリプトを使用して交換を実行できます。
find . -name "*.mp3" -type f -exec bash -c 'mv "$1" "${1/pronunciation_de_}"' bash {} \;
ファイル名は実行中のbashプロセスにパラメータ{}
として渡され、bashのパラメータ拡張機能が使用され、inが最初に表示される場合は空の文字列に置き換えられます。$1
${1/pronunciation_de_}
pronunciation_de_
$1
追加オプションを使用すると、通常のファイルのみが一致する-type f
ことを確認できます。
答え2
pronunciation_de_
名前で終わるすべてのファイルからプレフィックスを削除するには、名前が一致するファイルを検索して誤って.mp3
他pronunciation_de_*.mp3
のファイル名を変更しないようにする必要があります(これが起こる可能性は低い)。
行中心のテキスト編集ツール(sed
ファイル名など)を使用しないでください。シェルは、ファイル名からプレフィックスとサフィックス文字列を効率的に削除する方法を知っています。
以下を使用してfind
問題を解決できます。
find . -type f -name 'pronunciation_de_*.mp3' -exec sh -c '
for pathname do
newname=${pathname##*/} # removes directory path, leaves filename
newname=${newname#pronunciation_de_} # deletes the prefix string
mv -i "$pathname" "${pathname%/*}/$newname"
done' sh {} +
このコマンドは、転送されテストされたファイルfind
のパス名を生成し、これらのファイルを一括して短いインラインスクリプトに供給します。-type
-name
sh -c
このスクリプトは与えられたパス名を繰り返し、各パス名の新しい名前を作成します。
- 初期ディレクトリパスを削除し、パス名を次のよう
./some/path/pronunciation_de_werden.mp3
に変更します。pronunciation_de_werden.mp3
- プレフィックス文字列を削除
pronunciation_de_
しpronunciation_de_werden.mp3
ますwerden.mp3
。
このコマンドは、元のmv
ファイルを元のディレクトリの新しい名前に移動し、元のファイル(元のパス${pathname%/*}
名に展開されるディレクトリパス)の名前を変更します。
答え3
あなたの:
find . -name "*.mp3" -exec sed -i 's/pronunciation_de_//g' {} \;
ファイルの検索(次を含むすべてのタイプ定期的な、目次、シンボリックリンク、先入選出...)、名前は現在のジョブ以下で終わり.mp3
、各ファイルはプログラムと見つかったファイルを作業するファイルとして使用してsed
内部モードで実行されます。s/pronunciation_de_//g
しかし、sed
それはs
ストリームed
itorです。その使命は、テキストストリームを編集することです。ファイルを引数として与えると小川~であるコンテンツファイル名(名前ではありません)でsed
ファイル名は変更されません。ファイル名を変更するための標準コマンドはですmv
。これには、特にバッチの名前を変更するためのいくつかのコマンドが含まれる場合があります(ファイルを検索して名前を編集する機能が組み込まれている可能性があります)。mmv
、、、rename
。zmv
sed
その名前をストリームとして指定すると、それを使用してファイル名を編集できますが、これは非常に面倒で確実に実行するのが難しい場合があります。
LC_ALL=C find . -depth -name 'pronunciation_de_*.mp3' -exec sh -c '
ret=0
for file do
new_file=$(
printf '%s\n' "$file" |
sed "
:1
\$!{
N
b1
}
s|/pronunciation_de_\([^/]*\)\$|/\1|
"
)
mv -i -- "$file" "$newfile" || ret=$?
done
exit "$ret"' sh {} +
(テストされていません)
次のことがどのように必要かをご覧ください。
LC_ALL=C
ファイル名がロケールの文字エンコードでエンコードされない問題を回避します。-depth
葉を扱う前に枝を処理してください。sed
パイプ()を介して|
ファイルパスを提供し、他のパイプ()を介して出力をシェル変数として収集できるようにシェルを実行します$(...)
。- 一度に1行だけを処理し、
sed
ファイルパスを複数の行で構成できるため、sed
置換を実行する前にパターンスペースにすべての行を累積するように指示する必要があります。 - ファイルのデフォルト名のみが変更され、古いパスコンポーネントは変更されません。
-i
このオプションを使用すると、ユーザーにデータの損失を防ぐ機会を与えます。ただし、名前付きファイル./pronunciation_de_weil.mp3
と名前付きディレクトリがある場合はまだ役に立ちません。./weil.mp3
この場合、ファイル名は自動的に変更されます./weil.mp3/pronunciation_de_weil.mp3
。 GNUの実装には、このような状況を軽減するオプションがmv
あります。-T
zmv
(シェルの自動ローディング機能)との比較zsh
:
autoload zmv
zmv '(**/)pronunciation_de_(*.mp3)' '$1$2'
これには別の利点があります。
- 実行する前に、潜在的な競合を確認してください。どの名前変更
- 隠しファイルをスキップします(隠しファイルの名前も変更したい場合はそれを変更できます
zmv '(**/)pronunciation_de_(*.mp3)(#qD)' '$1$2'
)。
1sed
実装がこの非標準拡張をサポートし、次のパラメータがバックアップサフィックスと見なされないと仮定します。
答え4
バッチジョブの場合は、GNU Parallelを好みます。
ls -1 *.mp3 |
sed 's/pronunciation_de_//' |
parallel mv pronunciation_de_{} {}
sed
ファイル名からコンテンツを削除しましたpronunciation_de_
。それでは、、、…{}
のようになります。wählen.mp3
wange.mp3