/ / Bashサブストリングの置き換えに相当するシェル$ {foo / a / b} - bash、shell、find、sh

シェルの一般的なBashサブストリング置換$ {foo / a / b} - bash、shell、find、sh

bashの部分文字列置換のシェルに依存しない同等のものがありますか?

foo=Hello
echo ${foo/o/a} # will output "Hella"

私が使うことができるほとんどの時間 bash だからそれは問題ではありませんが、 find -exec それは動作しません。たとえば、すべての名前を変更する .cpp 〜へのファイル .c、私は使用したい:

# does not work
find . -name "*.cpp" -exec mv {} {/.cpp$/.c}

今のところ、私は以下を使用しています:

# does work, but longer
while read file; do
mv "$file" "${file/.cpp$/.c}";
done <<< $(find . -name "*.cpp")

スクリプトで使用できるソリューションが理想的です。

回答:

回答№1は4

使用 find そして -exec あなたはこれを行うことができます:

find . -name "*.cpp" -exec bash -c "f="$1"; mv "$f" "${f/.cpp/.c}"" - "{}" ;

しかし、これはフォークします bash -c 使用する各ファイル名ごとに xargs または for このようなループはパフォーマンス上の理由から優れています。

while IFS= read -d "" -r file; do
mv "$file" "${file/.cpp/.c}"
done < <(find . -name "*.cpp" -print0)

回答№2の場合は1

Btw、代わりに使用する bash 使用するだろう rename。あなたが クール バージョンの rename コマンドは、一緒に出荷されます perl できるよ:

find -name "*.cpp" -exec rename "s/.cpp$/.c/" {} +

上の例はあなたがGNUを所有していると仮定しています findutils現在のディレクトリがデフォルトであるため、これを渡す必要はありません。もしあなたがGNUを持っていなければ findutilsそれを明示的に渡す必要があります:

find . -name "*.cpp" -exec rename "s/.cpp$/.c/" {} +