Czy istnieje niezależna od powłoki równoważność zastąpienia podciągów Bash:
foo=Hello
echo ${foo/o/a} # will output "Hella"
Większość czasu mogę wykorzystać bash
więc to nie jest problem, jednak w połączeniu z find -exec
to nie działa. Na przykład, aby zmienić nazwę wszystkich .cpp
pliki do .c
, Chciałbym użyć:
# does not work
find . -name "*.cpp" -exec mv {} {/.cpp$/.c}
Na razie używam:
# does work, but longer
while read file; do
mv "$file" "${file/.cpp$/.c}";
done <<< $(find . -name "*.cpp")
Najlepiej byłoby, gdyby rozwiązanie, które można było wykorzystać w skryptach, było lepsze!
Odpowiedzi:
4 dla odpowiedzi № 1Za pomocą find
i -exec
możesz to zrobić:
find . -name "*.cpp" -exec bash -c "f="$1"; mv "$f" "${f/.cpp/.c}"" - "{}" ;
Jednak to się rozwidli bash -c
dla każdej nazwy tak używanej xargs
lub for
taka pętla jest lepsza ze względu na wydajność:
while IFS= read -d "" -r file; do
mv "$file" "${file/.cpp/.c}"
done < <(find . -name "*.cpp" -print0)
1 dla odpowiedzi nr 2
Btw, alternatywa dla używania bash
byłoby użyć rename
. Jeśli masz fajne wersja rename
polecenie, które jest wysyłane wraz z perl
możesz to zrobić:
find -name "*.cpp" -exec rename "s/.cpp$/.c/" {} +
Powyższy przykład zakłada, że masz GNU findutils
, mając to, nie musisz przekazywać bieżącego katalogu, ponieważ jest to ustawienie domyślne. Jeśli nie masz GNU findutils
, musisz go wyraźnie podać:
find . -name "*.cpp" -exec rename "s/.cpp$/.c/" {} +