Jak wsadowo zmieniać nazwy plików w terminalu macOS?

123

Mam folder z serią plików o nazwie:

prefix_1234_567.png
prefix_abcd_efg.png

Chciałbym zbiorczo usunąć jeden podkreślenie i środkową zawartość, aby wynik wyglądał następująco:

prefix_567.png
prefix_efg.png

Odpowiednie, ale nie do końca wyjaśniające:

kidnim
źródło
spójrz na zakres i metody podciągów NSString i NSMutableString
Grady Player,
1
Czy rozważałeś nieterminalne rozwiązania tego problemu? Przepływ pracy Automatora może z łatwością wykonywać tego typu operacje. Możesz utworzyć przepływ pracy automatu, aby zmienić nazwy wszystkich plików i zastąpić tekst _*_spacją.
Encryptic
Myślałem, że automator nie może robić symboli wieloznacznych
kidnim

Odpowiedzi:

234

W swoim konkretnym przypadku możesz użyć następującego bashpolecenia ( bashjest to domyślna powłoka w systemie macOS):

for f in *.png; do echo mv "$f" "${f/_*_/_}"; done

Uwaga: jeśli istnieje prawdopodobieństwo, że nazwy plików zaczynają się od -, umieść -- je przed nimi [1]:
mv -- "$f" "${f/_*_/_}"

Uwaga: echojest poprzedzonymv tak, aby przeprowadzić próbę. Usuń go, aby dokonać faktycznej zmiany nazwy.

Możesz go uruchomić z linii poleceń lub użyć w skrypcie.

  • "${f/_*_/_}"jest zastosowaniem bash interpretacji parametrów : (pierwszy) wzorzec dopasowania podłańcucha _*_jest zastępowany literałem_ , skutecznie odcinając środkowy token z nazwy.
  • Zauważ, że _*_jest to wzorzec (wyrażenie wieloznaczne, używane również do globowania), a nie wyrażenie regularne (aby dowiedzieć się o wzorcach, uruchomić man bashi wyszukać Pattern Matching).

Jeśli często zmieniasz nazwy plików, rozważ zainstalowanie specjalistycznego narzędzia, takiego jak renamenarzędzie oparte na Perlu . Na macOS możesz go zainstalować za pomocą popularnego menedżera pakietów Homebrew w następujący sposób:

brew install rename

Oto odpowiednik polecenia u góry rename:

rename -n -e 's/_.*_/_/'  *.png

Ponownie, to polecenie wykonuje próbę; usuń, -naby dokonać faktycznej zmiany nazwy.

  • Podobnie jak w bashrozwiązaniu, s/.../.../wykonuje podstawianie tekstu, ale - w przeciwieństwie do in bash- używane są prawdziwe wyrażenia regularne .

[1] Celem argumentu specjalnego --, który jest obsługiwany przez większość narzędzi, jest zasygnalizowanie, że kolejne argumenty powinny być traktowane jako argumenty (wartości), nawet jeśli wyglądają jak opcje, ponieważ zaczynają się od -, jak zauważa Jacob C.

mklement0
źródło
3
świetna odpowiedź, działała idealnie. Doceniam również to, że wróciłeś i zredagowałeś to, aby bardziej wyjaśnić i zapewnić bardziej eleganckie rozwiązanie, jeśli to powtórzę. jeszcze raz wielkie dzięki, bardzo pomocne
kidnim
4
Przykład używający dopasowanych zamienników ( .*-> $1), np. Zmień nazwę Foo bar S01E01 biz baz.extna S01E01.ext:rename -n -e 's/.*(S[0-9]{2}E[0-9]{2}).*(\.[a-z]{2,4})/$1$2/' *
Steve Robbins
2
Uwielbiam pomysł używania echodo suchych biegów. Dzięki za wskazówkę!
James Wright
Gorąco polecambrew install rename
Chris Redford
98

Aby zmienić nazwy plików, możesz użyć renamenarzędzia:

brew install rename

Na przykład, aby zmienić ciąg wyszukiwania we wszystkich nazwach plików w bieżącym katalogu:

rename -nvs searchword replaceword *

Usuń parametr „n”, aby zastosować zmiany.

Więcej informacji: man rename

David Thomas
źródło
1
OS Xwersje GNU bash( x86_64-apple-darwin ) nie zawierają narzędzia zmiany nazwy.
l'L'l
4
Dzięki, tak, musi być zainstalowany przezbrew install rename
David Thomas,
2
Ta wskazówka jest niesamowita! Wpisałem rename -vs GLYCOPHORIN GLYCC *i teraz automatycznie zmienia nazwę 450+ plików. I super szybko.
Sander W. van der Laan
3
Doskonały! Uwielbiam część „pokaż, co by się zmieniło”, ZANIM faktycznie zmieni nazwy rzeczy!
Ben Duffin,
3
Możesz również użyć wyrażenia regularnego. rename 's / 123 / onetwothree / g' *
Bryan
12

Możesz użyć sed:

ls * | sed -e 'p;s@_.*_@_@g' | xargs -n2 mv

wynik:

prefix_567.png prefix_efg.png

* aby najpierw wykonać pracę na sucho, wymień mv na końcuecho

Wyjaśnienie:

  • e: opcjonalne tylko dla 1 polecenia sed.
  • p: wypisuje dane wejściowe do seda, w tym przypadku będzie to oryginalna nazwa pliku przed jakąkolwiek zmianą nazwy
  • @: jest zamiennikiem znaku /, aby uczynić sed bardziej czytelnym. Oznacza to, że zamiast używać seda s / search / replace / g, użyj s @ search @ replace @ g
  • _. *: podkreślenie to znak zmiany znaczenia odnoszący się do rzeczywistego znaku „.” znak zero lub więcej razy (w przeciwieństwie do DOWOLNEGO znaku w wyrażeniu regularnym)
  • -n2: wskazuje, że są 2 wyjścia, które muszą zostać przekazane do mv jako parametry. dla każdego wejścia z ls , to polecenie sed wygeneruje 2 wyjścia, które następnie zostaną przekazane do mv.
l'l'l
źródło
1
Sprytne, choć nieco tajemnicze rozwiązanie. Uogólnienie tego, tak aby obsługiwać również nazwy plików z osadzonymi spacjami, staje się jeszcze bardziej tajemnicze: ls * | xargs -I % bash -c 'echo mv "%" "$(sed 's@_.*_@_@' <<<"%")"'(usuń, echoaby faktycznie zmienić nazwę).
mklement0
2
Tajemna? Uwielbiam to!
Bilal Akil
7

Miałem pakiet plików, który wyglądał tak: be90-01.png i potrzebowałem zmienić myślnik na podkreślenie. Użyłem tego, co działało dobrze:

for f in *; do mv "$f" "`echo $f | tr '-' '_'`"; done
JanB
źródło
2

możesz zainstalować renamepolecenie za pomocą brew. po prostu zrób brew install renamei użyj go.

Józef Nisim
źródło
1

Za pomocą mmv

mmv '*_*_*' '#1_#3' *.png
αғsнιη
źródło
musisz najpierw zainstalować sudo apt-get install mmv.
αғsнιη
1
Biorąc pod uwagę, że był to OS X, poprawna procedura instalacji to brew install mmv.
buckaroo1177125
1

Spróbuj tego

for i in *.png ; do mv "$i" "${i/remove_me*.png/.png}" ; done

Oto inny sposób:

for file in Name*.png; do mv "$file" "01_$file"; done
Thiago
źródło