Unikaj zamiany spacji podczas zmiany nazwy plików

10

Próbuję zmienić nazwę plików w ten sposób:

for file in *;
do
mv -i "$file" "$(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')";
done

Ale sedpolecenie zastępuje wszystkie spacje _.

Jak mogę edytować sedpolecenie, aby zawierało spacje wraz z określonymi znakami? Próbowałem używać, \sale to nie działa ...

EDYCJA:
Na przykład: trip: hillnazwa pliku powinna zostać zmieniona:, trip_ hillale powoduje to powyższe polecenie trip__hill.

Zanna
źródło
Przenoszę niektóre pliki z systemu Linux na Mac. Ale z jakiegoś powodu system Mac nie może odczytać wszystkich nazw plików, dlatego próbuję zmienić nazwę moich plików. Dodanie spacji do powyższego polecenia nie działa. I masz rację: chcę zamienić wszystkie znaki na „_” oprócz tych określonych. I nie wiem, jak uwzględnić znak spacji.
Pamiętaj, że próbuję zastąpić wszystkie znaki znakiem „_” oprócz tych określonych. Nazwa pliku nie ma określonego wzorca, więc nie mogę użyć tej komendy perl.

Odpowiedzi:

11

Nie parsuj nazw plików za pomocą sed! Dane wyjściowe echo "$file"mogą nie być wiarygodne.

Zastosowanie rename. 17.10 musisz go najpierw zainstalować

sudo apt install rename

Następnie:

rename -n -- 's/[^-A-Za-z0-9_ .]/_/g' *

Notatki

  • usuń -npo przetestowaniu, aby faktycznie zmienić nazwę plików
  • -- koniec opcji w przypadku, gdy dowolny plik zaczyna się od -
  • [^-A-Za-z0-9_ .]znaki, których nie chcemy zastępować - umieść na -początku lub na końcu, aby nie wskazywały zakresu (jest traktowane dosłownie w tych pozycjach).
  • Klasa może zawierać spacje
  • . jest traktowany dosłownie (w innych kontekstach wyrażeń regularnych oznacza każdą postać i musi być poprzedzony znakiem ucieczki).

Działa to również w sed:

$ echo 'trip: hill' | sed 's/[^-A-Za-z0-9 _.]/_/g'
trip_ hill

Jeśli dodam spację na końcu w twojej wersji, pojawia się błąd:

$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._- ]/_/g'
sed: -e expression #1, char 22: Invalid range end

Ale -na końcu działa:

$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._ -]/_/g'
trip_ hill

Być może więc pozycja łącznika spowodowała problem podczas dodawania spacji. Ale rada, aby nie analizować nazw plików, stoi!

Zanna
źródło
To polecenie działa, dziękuję. Wyraźnie zidentyfikowałeś także błędy w poleceniu, którego użyłem.
2
Jeszcze raz dziękuję. Należy pamiętać, że nie ma potrzeby używania ukośnika „\” w przypadku korzystania z sed. Ponieważ dodaje to „\” do listy ignorowanych znaków.
2
@latach To odwrotny ukos, ale masz całkowitą rację. Po przetestowaniu i przekopaniu się odkryłem, że .jest to dosłowne w klasie postaci. TIL!
Zanna,
2

Możesz także po prostu użyć powłoki, rozszerzenie parametrów Bash może zastąpić:

for f in ./* ; do
    mv "$f" "${f//[^-A-Za-z0-9._ ]/_}"
done

Podwójny ukośnik nakazuje zastąpienie wszystkich dopasowań poza tym, że składnia jest prosta.

ilkkachu
źródło