Oto bezpośrednia poprawka twojego podejścia:
find . -type f -name 'file*' -exec sh -c 'x="{}"; mv "$x" "${x}_renamed"' \;
Jest to jednak bardzo kosztowne, jeśli masz wiele pasujących plików, ponieważ uruchamiasz nową powłokę (która wykonuje a mv
) dla każdego dopasowania. A jeśli masz zabawne postacie w dowolnej nazwie pliku, to wybuchnie. Bardziej wydajne i bezpieczne podejście jest następujące:
find . -type f -name 'file*' -print0 | xargs --null -I{} mv {} {}_renamed
Ma także tę zaletę, że pracuje z dziwnie nazwanymi plikami. Jeśli find
obsługuje, można to zmniejszyć do
find . -type f -name 'file*' -exec mv {} {}_renamed \;
xargs
Wersja jest przydatna, gdy nie jest używany {}
, tak jak w
find .... -print0 | xargs --null rm
Tutaj rm
jest wywoływany raz (lub wiele plików wiele razy), ale nie dla każdego pliku.
Usunąłem basename
w tobie pytanie, ponieważ prawdopodobnie jest złe: przeniósłbyś foo/bar/file8
się file8_renamed
, nie foo/bar/file8_renamed
.
Edycje (zgodnie z sugestiami w komentarzach):
- Dodano skrócone
find
bezxargs
- Dodano naklejkę bezpieczeństwa
x
jest to bezużyteczne:find . -type f -name 'file*' -exec mv {} "{}_renamed" \;
xargs
wersja ma taką samą wydajność jak pierwszy przykład /x
Jest tam tylko bezpośrednio naprawić podejście Pytający za.{}
bezpośrednio wsh -c "…"
poleceniu shell ( ) jest bardzo niebezpieczne - zawsze powinieneś przekazać ją jako argument. (2) Nie wszystkie wersjefind
obsługują{}_renamed
konstrukcję. (3) Nie rozumiem twojego stwierdzenia, którexargs
jest przydatne do usuwania plików (w przeciwieństwie do zmiany ich nazw).xargs
nie jestmv
vs.rm
, ale użycie{}
vs. bez. Pierwsza jest podobna domv file1 file1_renamed; mv file2 file2_renamed
drugiejrm file1 file2
.Po wypróbowaniu pierwszej odpowiedzi i odrobinie z nią zabawy okazało się, że można to zrobić nieco krócej i mniej skomplikowane, używając
-execdir
:Wygląda na to, że powinien zrobić dokładnie to, czego potrzebujesz.
źródło
find
implementacjom, które obsługują,-execdir
a{}
nie jako całość, jest również najbezpieczniejszy. Możesz jednak dodać coś-i
domv
tego (i-T
jeślimv
go wspierasz)mv
pytaniu, lub oprócz tego, możesz (bez wątpienia w zależności od tego, czy twoja implementacjafind
go obsługuje) również użyć,-okdir
które wypisze polecenie do wykonania przed jego wykonaniem.-depth
to także dobry pomysł, jeśli zamierzasz także dotykać nazw katalogów.-execdir
ma jeden bardzo irytujący minus,find
odmawia robienia czegokolwiek, jeśliPATH
zawiera jakieś ścieżki względne ... askubuntu.com/questions/621132/ ...find: The relative path XXX is included in the PATH environment
Innym podejściem jest użycie
while read
pętli nadfind
wyjściem. Pozwala to na dostęp do każdej nazwy pliku jako zmienna, że można manipulować bez konieczności martwienia się o dodatkowe koszty / potencjalnych problemów bezpieczeństwa tarła oddzielnysh -c
proces przy użyciufind
„s-exec
opcję.A jeśli używana powłoka obsługuje
-d
opcję określaniaread
separatora, możesz obsługiwać pliki o dziwnie nazwanych nazwach (np. Z nową linią), używając następujących poleceń :źródło
Chcę rozwinąć pierwszą odpowiedź i zauważyć, że to nie zadziała, aby dołączyć do nazwy pliku, ponieważ
./
przedrostek ścieżki znajduje się w argumencie nazwy pliku.Modyfikując odpowiedź Thomasa Erkera, uważam, że jest to bardziej ogólne podejście
Opcje xargs:
--null
Wskazuje, że każdy przekazany argumentstdin
kończy się znakiem null (\0
). W ten sposób nazwa pliku może zawierać spacje, w przeciwnym razie każde słowo będzie traktowane jako inny parametrmv
polecenia.-I replace-str
Każde wystąpieniereplace-str
zostanie zastąpione argumentem odczytanym zstdin
. Możesz więc zmienić go na inny ciąg, jeśli jest to potrzebne.źródło
pringf "%f\0"
zamiast zamiastprint0
?-print0
spowoduje utworzenie./
prefiksów, jeśliPATTERN
zawiera metaznaki powłoki, które przeszkadzają w zmianie nazwy na coś, co poprzedza oryginalne nazwy. (np. zmień nazwę0 - foo.txt
na00 - foo.txt
,1 - bar.txt
na01 - bar.txt
itp.)Udało mi się zrobić coś podobnego z
for
,find
, imv
.Znajduje wszystkie
config.yml
pliki i zmienia ich nazwy naconfig.yml.bak
źródło
for
i wykonać operację zbiorczą.