Jak zmieniać nazwy plików i zamieniać znaki?

11

Mam grupę plików, które mają :(dwukropek) w nazwie. Muszę wymienić :z -(kreską).

Czy istnieje prosty sposób na zrobienie tego w skrypcie?

Przykładowa nazwa pliku: 2013-10-11:11:52:08_055456663_045585_.txt

Ptaszyna
źródło

Odpowiedzi:

17

Powinien wystarczyć prosty 1-liniowy (zakłada shpowłokę kompatybilną z Posix ):

for f in *:*; do mv -v "$f" $(echo "$f" | tr ':' '-'); done

Wyjaśnienie:

  • for ... in ...; do ...; donejest pętlą

  • *:* dopasowuje wszystkie pliki i katalogi w bieżącym katalogu, które mają :w swojej nazwie

  • f jest przypisywany kolejno do każdej takiej nazwy pliku w pętli

  • mvzmienia swój pierwszy argument na drugi; -v(verbose) prosi go o wydrukowanie tego, co robi; ta opcja jest specyficzna dla GNU-utils , więc jest dostępna w systemie Linux, ale nie w systemie Solaris

  • $(...) wykonuje kod w podpowłoce i zastępuje dane wyjściowe

  • echo wypisuje swój argument na standardowe wyjście

  • tr odczytuje standardowe wyjście i tłumaczy znaki zgodnie z dostarczoną mapą

Jeśli używasz bash , możesz uniknąć tworzenia dodatkowej powłoki ( $()) z podprocesami ( tr), zastępując $(...)${f//:/-}.

sds
źródło
+1 za prostą roboczą odpowiedź, choć może przydać się trochę więcej wyjaśnień. Np. for f inPętla ... to pętla, która iteruje wszystkie pliki w bieżącym katalogu, w których pliki muszą się zgadzać *:*. (Co dzieje się z reżimami, które pasują?). Polecenie move to move oldname newname, w którym nowa nazwa jest generowana przez wykonanie powłoki za pomocą $( subshell here ). Co tr, ...
Hennes,
@Hennes: to jest superużytkownik - czy naprawdę muszę zagłębiać się w tego rodzaju szczegóły? No cóż, proszę bardzo ...
sds
Nie. Gdyby istniała prawdziwa potrzeba, nie dałbym +1. I rozumiem, co to robi. Myślę, że jest to miłe dla wielu innych czytelników.
Hennes
2
Można wymienić $(echo "$f" | tr ':' '-')z "${f//:/-}"i uniknąć powłoki w tle, rury i połączenia zewnętrznego programu. Myślę, że to bzdura, ale eh. Zobacz tutaj .
evilsoup
@evilsoup Rzeczywiście; w przypadku małych zestawów danych nie robi to dużej różnicy (i można sprzyjać czytelności), ale byłbyś zaskoczony, jak szybko coś takiego się sumuje. Ostatnio mnie to ugryzło; przepisywanie skryptu tak, że dwie proste komendy ciąg masujące nie były już konieczne łatwo skrócić czas realizacji o 90% lub więcej, które na dużą zbioru danych przetłumaczony na kilka minut czasu wykonywania wallclock.
CVn
6

Jak napisałem w innym poście, renamenarzędzie może załatwić sprawę. Musisz tylko wpisać rename s/:/-/ <files to rename> To zastępuje każdy dwukropek myślnikiem we wszystkich nazwach plików na końcu, tj2013-10-*

Oto link do mojego innego postu

noggerl
źródło
1

Jestem pewien, że profesjonalista UNIX mógłby to zrobić za pomocą bash, ale oto moja szybka i brudna wersja z ruby.

path_to_files = "/home/username/wrongnames/"
filenames = `ls #{path_to_files}`.split
filenames.each do |fn|
  `mv #{path_to_files + fn} #{path_to_files + fn.gsub(/:/, "-")}`
end

ustaw path_to_files na ścieżkę do twoich błędnie nazwanych plików. zapisz powyższy kod w pliku o nazwie rename.rb, a następnie:

username@machinename$ ruby rename.rb
shupru
źródło
@sds zapewnia znacznie lepszą odpowiedź. Czy powinienem usunąć swoją odpowiedź? Jestem nowy w Stackoverflow.
shupru
1
Nie; nadal ma znaczącą wartość. :)
Blacklight Shining
2
Istnieje jednak kilka poważnych wad tej odpowiedzi, które mogą być istotne i na pewno warto o nich wiedzieć. (Może to nadal być przydatne, ale ostrzegacz i tak dalej.) Przede wszystkim wygląda na to, że źle się zepsuje, gdy napotka nazwy plików z białymi spacjami (nie tylko w klasycznej nowej linii przypadku awarii). Ponadto, nawet jeśli nie dotyczy to spacji, powinieneś zacytować nazwę pliku w wywołaniu powłoki, aby chronić wszelkie inne znaki specjalne w nazwach plików przed przetwarzaniem przez powłokę (chociaż nie wiem dokładnie, jak działa operator odwrotności Ruby ).
CVn
1

Jeśli masz tylko jeden lub kilka plików, możesz dokonać zmiany nazwy:

  1. Przechowywać wzorzec nazwy pliku są kierowane jako zmienna: p="201*".
  2. Zapisać starą nazwę pliku , który chcesz zmienić nazwę: old_name=$(ls | grep $p).
  3. Zapisz nową nazwę pliku z niezbędnymi zamiennikami znaków:

    new_name=$(ls | grep $p | sed 's/:/_/g')        # Using 'sed'
    
                OR
    
    new_name=$(ls | grep $p | tr ':' '_')           # Using 'tr'
    

Czyszczenie bonusów :
  a. Jeśli ze względu na jednolitość chcesz zastąpić myślniki (-) wraz z dwukropkami (:) znakami podkreślenia (_), możesz to zrobić:

    new_name=$(ls | grep $p | tr ':-' '_');

  b. Jeśli chcesz, aby .txtzniknął również ostatni znak podkreślenia (tuż przed ), ustaw new_namezmienną jako:

    new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./')
  1. Teraz zmień nazwę pliku zgodnie z potrzebami: mv $old_name $new_name

         Uwaga: mvnie powiedzie się, jeśli w nazwie znajduje się jakakolwiek nazwa pliku w operacji zmiany nazwy spaces. W takim przypadku zawiń odpowiednie zmienne w cudzysłów, takie jak:
mv "$old_name" $new_name LUB mv $old_name "$new_name" LUB mv "$old_name" "$new_name"


Jednowarstwowe

1a: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | sed 's/:/_/g'); mv $old_name $new_name

1b: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':' '_'); mv $old_name $new_name

2: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_'); mv $old_name $new_name

3: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./'); mv $old_name $new_name
Dut A.
źródło
0

za pomocą zmiany nazwy :

$ renamer --find ":" --replace "-" *
Lloyd
źródło
Myślę, że zainstalowanie pełnego środowiska node.js do zmiany nazw plików to trochę za dużo. renamejest narzędziem, które jest wstępnie zainstalowane w wielu dystrybucjach systemu Linux. Ale myślę, że dla systemu Windows to narzędzie może być świetne.
noggerl
0

Może to być przesada, ale możesz zmienić nazwę dowolnego znaku specjalnego za pomocą skryptu pod linkiem podanym w tej odpowiedzi:

/superuser//a/858671/365691

A.Danischewski
źródło