Chcę zmienić nazwę plików, aby zmienić ich rozszerzenie, skutecznie starając się to osiągnąć
mv *.txt *.tsv
Ale robiąc to, otrzymuję:
* .tsv nie jest katalogiem
Wydaje mi się nieco dziwne, że pierwsze 10 hitów Google mv
powinno tak działać.
Chcę zmienić nazwę plików, aby zmienić ich rozszerzenie, skutecznie starając się to osiągnąć
mv *.txt *.tsv
Ale robiąc to, otrzymuję:
* .tsv nie jest katalogiem
Wydaje mi się nieco dziwne, że pierwsze 10 hitów Google mv
powinno tak działać.
Odpowiedzi:
Po wydaniu polecenia:
mv *.txt *.tsv
powłoka, załóżmy bash, rozwija symbole wieloznaczne, jeśli są jakieś pasujące pliki (w tym katalogi). Lista plików jest przekazywana do programu tutaj mv
. Jeśli nie zostaną znalezione żadne dopasowania, wersja nierozwinięta jest przekazywana.
Znowu: powłoka rozszerza wzorce, a nie program.
Mnóstwo przykładów jest chyba najlepszym sposobem, więc zaczynamy:
$ ls
file1.txt file2.txt
$ mv *.txt *.tsv
Teraz w mv
linii dzieje się, że powłoka rozwija *.txt
się do pasujących plików. Ponieważ nie ma *.tsv
plików, które nie zostaną zmienione.
mv
Polecenie nazywa się z dwóch specjalnych argumentów :
argc
: Liczba argumentów, w tym program.argv
: Tablica argumentów, w tym program jako pierwszy wpis.W powyższym przykładzie byłoby to:
argc = 4
argv[0] = mv
argv[1] = file1.txt
argv[2] = file2.txt
argv[3] = *.tsv
mv
Kontrola programu, aby zobaczyć czy ostatni argument *.tsv
jest katalogiem. Ponieważ tak nie jest, program nie może kontynuować pracy, ponieważ nie jest przeznaczony do łączenia plików. (Zazwyczaj przenieś wszystkie pliki do jednego.) Nie twórz katalogów według kaprysu.
W rezultacie przerywa działanie i zgłasza błąd:
mv: target ‘*.tsv’ is not a directory
Teraz, jeśli zamiast tego powiesz:
$ mv *1.txt *.tsv
mv
Polecenie jest wykonywane z:
argc = 3
argv[0] = mv
argv[1] = file1.txt
argv[2] = *.tsv
Teraz ponownie mv
sprawdź, czy *.tsv
istnieje. W przeciwnym razie plik file1.txt
zostanie przeniesiony do *.tsv
. To znaczy: nazwa pliku zmienia się *.tsv
na gwiazdkę i wszystko.
$ mv *1.txt *.tsv
‘file1.txt’ -> ‘*.tsv’
$ ls
file2.txt *.tsv
Jeśli zamiast tego powiedziałeś:
$ mkdir *.tsv
$ mv *.txt *.tsv
mv
Polecenie jest wykonywane z:
argc = 3
argv[0] = mv
argv[1] = file1.txt
argv[1] = file2.txt
argv[2] = *.tsv
Ponieważ *.tsv
teraz jest katalog, pliki są tam przenoszone.
Teraz: używając poleceń, takich jak some_command *.tsv
kiedy rzeczywiście chcesz zachować symbol wieloznaczny, zawsze powinieneś go zacytować. Cytując, zapobiegasz rozszerzaniu symboli wieloznacznych, jeśli powinny być jakieś dopasowania. Powiedz np mkdir "*.tsv"
.
Rozszerzenie można wyświetlić jeszcze, jeśli wykonasz na przykład:
$ ls
file1.txt file2.txt
$ mkdir *.txt
mkdir: cannot create directory ‘file1.txt’: File exists
mkdir: cannot create directory ‘file2.txt’: File exists
Teraz: mv
polecenie może i działa na wielu plikach. Ale jeśli jest ich więcej niż dwa, ostatni musi być katalogiem docelowym. (Opcjonalnie możesz użyć tej -t TARGET_DIR
opcji, przynajmniej dla GNU mv.)
Więc to jest OK:
$ ls -F
b1.tsv b2.tsv f1.txt f2.txt f3.txt foo/
$ mv *.txt *.tsv foo
Tutaj mv
będzie się nazywać z:
argc = 7
argv[0] = mv
argv[1] = b1.tsv
argv[2] = b2.tsv
argv[3] = f1.txt
argv[4] = f2.txt
argv[5] = f3.txt
argv[6] = foo
i wszystkie pliki trafiają do katalogu foo
.
Co do twoich linków. Podałeś jeden (w komentarzu), w którym mv
wcale nie wspomniano, ale rename
. Jeśli masz więcej linków, które możesz udostępnić. Podobnie jak w przypadku stron podręcznika, w których twierdzisz, że jest to wyrażone.
Wiem, że to nie odpowiada na twoje pytanie, ale jeśli szukałeś innego sposobu zmiany nazwy plików w porównaniu do pętli obejścia, dlaczego nie użyć find
? Używałem tego polecenia wiele razy, aby zastąpić rozszerzenia plików w dużych katalogach setkami tysięcy plików. Powinno to działać na każdym systemie zgodnym z POSIX:
find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;
Podział poleceń:
'
.
' => ścieżka wyszukiwania zaczynająca się od bieżącego katalogu oznaczonego przez '. „
-name
=> ustaw szukaną nazwę dopasowania (w tym przypadku wszystkie pliki, które kończą się.gappedPeak
)
-exec
=> wykonaj następujące polecenie przy każdym dopasowaniu
sh -c
=> 'exec' tworzy niezależne środowisko powłoki dla każdego dopasowania
mv "$1" "${1%.gappedPeak}.bed"
=>mv
pierwsza zmienna (oznaczona przez $ 1 ), która jest bieżącą nazwą pliku, do nowej nazwy. Tutaj wykonuję dopasowanie podciągu i usuwam; więc weź najpierw var, $ 1 i użyj,%
aby usunąć.gappedPeak
z ciągu..bed
Na końcu po prostu skleja pozostałą zmienną, która jest teraz po prostu , z , tworząc nową nazwę pliku.test#
.bed
test#.bed
Podkreślenie jest symbolem zastępczym dla 0 USD
{}
Otrzymuje każdego (*.gappedPeak
) pliku znalezionego przezfind
polecenia i staje $ 1 dosh
komendy.
\;
oznacza koniec-exec
polecenia. Możesz także użyć';'
lub";"
.
Przykład:
[user@before]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.gappedPeak
[user@after]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.bed
file.abc
-> blub.xyz
w wielu katalogach podrzędnych:find . -name "file.abc" -exec sh -c 'mv "$1" "$(dirname $1)/blub.xyz"' _ {} \;
mv *.txt *.tsv
nie działa; mv
może zmienić nazwę tylko jednego pliku na raz. Albo źle zrozumiałeś wyjaśnienia, albo są w błędzie.
mmv
i rename
może zmieniać nazwy kilku plików jednocześnie. Ale istnieją dwie wersje, rename
które są nazywane inaczej. Tutaj powinno być wiele pytań.
rename
, a nie mv
.
mv *.txt *.tsv
mv
nie (zwykle) nie widzi *.txt
lub wyświetla *.tsv
nazwy plików z rozszerzeniem powłoki. Liczba plików rozwijanych przez te symbole wieloznaczne byłaby „losowa”. Jedyną sytuacją, w której to działa, jest plik o nazwie, *.txt
którego nazwa zostanie zmieniona na (dosłownie) *.tsv
(bez cytowania bash
opcji nullglob
nie można ustawić).
foo.txt
i jedną o nazwie będzie zastąpić istniejący plik ...baz.tsv
mv *.txt *.tsv
.tsv
Na przykład, jeśli masz asd.txt
i qwe.txt
pliki w katalogu po uruchomieniu polecenia mv *.txt *.tsv
, próbuje przenieść te dwa pliki do katalogu o nazwie *.tsv
. Ponieważ nie ma takiego katalogu, pojawia się błąd.
rename(1)
rename
jest skryptem perla autorstwa Larry'ego Walla, twórcy perla. Wymaga wyrażenia regularnego Perla i działa na nazwie pliku.
rename 's/\.txt$/.tsv/' *.txt
Jeśli musisz zainstalować rename
na Debian / Ubuntu, możesz to zrobić
sudo apt install rename
Inną opcją do rozważenia jest użycie:
cp -p *.txt *.tsv
rm -f *.txt
*.txt
pliki *.tsv
, zachowując ich atrybuty za pomocą -p
flagi.*.txt
mv
która po prostu zmienia katalog / nazwę pliku bez przenoszenia plików, chyba że znajdują się na innej partycji.