Co robi `mv ./*` bez określania miejsca docelowego?
27
Przypadkowo zapomniałem podać miejsce docelowe przed naciśnięciem klawisza Return. Gdzie mv ./*bez podania miejsca docelowego przenieść pliki i katalogi z bieżącego katalogu?
„Jestem zaskoczony, że mvakceptuje 1 argument” Nie. Akceptuje wszystkie argumenty, które powłoka przekazała mu po rozwinięciu pliku *.
glglgl
Odpowiedzi:
41
Jeśli ostatnim argumentem był katalog, po prostu przeniosłeś wszystkie pliki i katalogi z bieżącego katalogu roboczego (oprócz tych, których nazwy zaczynają się od kropek) do tego katalogu. Jeśli były dwa pliki, pierwszy plik mógł zastąpić drugi plik.
Oto kilka demonstracji:
Więcej niż dwa pliki, a ostatnim argumentem jest plik
$ mkdir d1 d2 d3
$ touch a b c e
$ mv *
mv: target 'e' is not a directory
Więcej niż dwa pliki, a ostatnim argumentem jest katalog
$ mkdir d1 d2 d3
$ touch a b c
$ mv -v *
'a' -> 'd3/a'
'b' -> 'd3/b'
'c' -> 'd3/c'
'd1' -> 'd3/d1'
'd2' -> 'd3/d2'
Dwa pliki
$ touch a b
$ mv -v *
'a' -> 'b'
Dalsze wyjaśnienia
Powłoka rozszerza glob ( *) na argumenty dla mv. Glob jest zwykle rozwijany w kolejności alfabetycznej. mvzawsze widzi listę plików i katalogów. Nigdy nie widzi samej globu.
Polecenie mvobsługuje dwa typy przenoszenia. Jednym jest mv file ... directory. Drugi to mv old-file-name new-file-name(lub mv old-file-name directory/new-file-name).
Najpierw stworzę bazę testową - 5 plików i jeden folder:
touch file1 file2 file3 file4 file5
mkdir folder
Następnie uruchomię polecenie testowe. Ta -vopcja określa, że chcę, aby każde polecenie wykonywane przez powłokę było drukowane stderr. Ta -xopcja określa, że chcę to samo wydrukować stderr- ale chcę, aby zrobiono to po ocenie polecenia, ale przed uruchomieniem go przez powłokę.
Widzicie więc, że po poleceniu, które karmię powłokę, echo mv *po poleceniu, które wykonuje powłoka po* rozwinięciu, echo mvnastępują wszystkie pliki i folder.
Kiedy więc uruchomisz polecenie w powłoce skonfigurowanej z domyślnymi opcjami, takimi jak mv *powłoka, rozwija się do *słowa lista argumentów wszystkich plików w bieżącym katalogu posortowana według ustawień regionalnych. Wykonuje syscall exec(ve)dla mv(zasadniczo) z dołączoną listą argumentów. mvOtrzymuje więc wszystkie argumenty, gdy powłoka je globalizuje i sortuje. Oprócz robienia stracetych efektów, możesz ponownie użyć debugowania w następujący sposób:
sh -s -- mv * <<\SCRIPT
sed -n l /proc/$$/cmdline
echo "$@"
SCRIPT
Zasadniczo powłoka jest wykonywana mvz zawartością katalogu (jeśli nie jest pusty i nie zawiera plików / folderów o nazwach rozpoczynających się od .) jako listy argumentów. mvPOSIX jest określony interpretować jako ostatecznego argumentu katalogu, jeśli jest ona wywoływana z więcej niż dwóch argumentów - w ten sam sposób lnjest (bo w rzeczywistości są one bardzo podobne narzędzia w funkcji bazowych) .
W pierwszej formie streszczenia mvnarzędzie przenosi plik nazwany przez operand plik_źródłowy do miejsca docelowego określonego przez plik_cel . Ten pierwszy formularz streszczenia zakłada się, gdy ostatni operand nie nazywa istniejącego katalogu i nie jest dowiązaniem symbolicznym odnoszącym się do istniejącego katalogu. W tym przypadku, jeśli plik_zrodlowy nazwy pliku non-katalog i target_file kończy wleczonego /slashcharakterem, mvtraktuje to jako błąd i nie ma plik_zrodlowy argumenty będą przetwarzane.
W drugim formularzu streszczenia mvprzenosi każdy plik nazwany operandem pliku źródłowego do pliku docelowego w istniejącym katalogu nazwanym przez operand katalog_docelowy lub do którego odwołuje się, jeśli katalog_docelowy jest dowiązaniem symbolicznym do istniejącego katalogu. Ścieżką docelową dla każdego pliku_źródłowego jest konkatenacja katalogu docelowego, pojedynczy /slashznak, jeśli cel nie kończy się na /slash, oraz ostatni składnik nazwy pliku źródłowego . Ta druga forma jest zakładana, gdy końcowy operand nazywa istniejący katalog.
Więc jeśli *rozwija się do:
dwa pliki
Powinieneś mieć tylko jeden plik, od pierwszego renameddo drugiego po drugim unlinked.
jeden lub więcej plików, a następnie ostatni katalog lub link do jednego
Powinieneś mieć tylko jeden katalog lub link do jednego, do którego właśnie przeniesiono całą poprzednią zawartość jego rodzica.
coś jeszcze
Powinieneś otrzymać komunikat o błędzie i satysfakcjonujące westchnienie ulgi.
tak, używając starej shrzeczy, zapomniałem o debugowaniu z tym, ale jeśli chodzi o moje oryginalne pytanie, oznacza to, że problemem nie jest powłoka mv? To paskudne, jest prostsze niż początkowo myślałem, ale to prawdziwa pułapka.
user2485710,
5
@ user2485710, kluczową kwestią jest to, że w Uniksie powłoka jest odpowiedzialna za rozwijanie symboli wieloznacznych przed przekazaniem argumentów wiersza poleceń do polecenia. W systemie Windows każde polecenie musi rozwinąć same symbole wieloznaczne. Pozwala to powłokom uniksowym oferować zaawansowane funkcje symboli wieloznacznych, które działają z dowolnymi poleceniami.
cjm
2
@mikeserv, biorąc pod uwagę fakt, że te pliki nie były tak ważne, rzuciłem się na czyszczenie i przejdź do następnego kroku, ale mogę potwierdzić rzeczy, jak teraz pojawiają się w mojej edycji mojego pierwszego postu / pytania.
user2485710,
6
@mikeserv tl; dr, czy *to nie pojedynczy argument? Dobrze? :)
Bernhard
1
@Bernhard - właściwie to jedyny przypadek, którego nie opisałem - bo może tak być.
mikeserv
18
Najpierw powłoka rozszerza się ./*na wszystkie pliki w bieżącym katalogu (z wyjątkiem plików zaczynających się od kropki).
w przypadku braku lub tylko jeden plik jest: mvnie
jeśli są dwa pliki: pierwszy jest przenoszony do drugiego (który w związku z tym ginie)
jeśli są więcej niż dwa pliki:
jeśli ostatni jest katalogiem: wszystkie pliki są przenoszone do tego katalogu
Jeśli jeden plik zawiedzie, dlaczego tak nie jest?
Noumenon
@Noumenon Nie rozumiem twojego komentarza. mvzwraca komunikat o błędzie, jeśli jest wywoływany tylko z jednym argumentem.
jofel
Masz rację. To samo polecenie z mojej historii daje teraz, missing destination file operand after *filename*choć wczoraj tak nie było.
Noumenon
4
Podczas pisania mv ./*powłoka rozwija się ./*przed uruchomieniem mv.
Kilka rzeczy do zapamiętania:
Jeśli ./*zostanie rozwinięte do mniej niż 2 argumentów mv, logicznie spowoduje błąd.
./* zwykle rozwija się do każdego pliku (w tym katalogu) obecnego w bieżącym katalogu i nie zaczyna się od kropki.
Możesz kontrolować, co się ./*rozwija, czytając dokumentację swojej powłoki ( man 7 globjest punktem wejścia do tematu). Różne muszle będą miały różne opcje.
Powłoka rozwija symbol wieloznaczny *do listy zawartości katalogu. Następnie powłoka przekazuje tę pełną listę do polecenia. Polecenie nigdy nie widzi *.
Polecenie mv file1 file2 ... filen directoryjest bardzo mało prawdopodobne, aby w ogóle mieć nic wspólnego z *.
mikeserv
@Mike: Moja odpowiedź wskazuje, że ostatni etap rozbudowy powłoki skutecznie przekształca ten drugi w poprzedni. Nieświadomość tego wydaje się być przyczyną zamieszania PO.
RedGrittyBrick
tak, ale chodzi mi o to, że powłoka nie rozszerzyłaby *się, file dirchyba że istnieją jakieś ustawienia regionalne, w których dnastępuje f.
mikeserv
@mikeserv: Istnieje taka lokalizacja, mój przykład to cut & paste z Putty łączącej się z systemem CentOS 5.6 GNU / Linux.
RedGrittyBrick
jakie to ustawienie regionalne? twój przykład jest taki, a b c dktóry nie jest file ... dir. I tylko komentuje w ogóle, ponieważ nie wspominając o porządek wszędzie, a tylko powiedzieć, że *staje się file ... dirco nie stało.
mv
akceptuje 1 argument” Nie. Akceptuje wszystkie argumenty, które powłoka przekazała mu po rozwinięciu pliku*
.Odpowiedzi:
Jeśli ostatnim argumentem był katalog, po prostu przeniosłeś wszystkie pliki i katalogi z bieżącego katalogu roboczego (oprócz tych, których nazwy zaczynają się od kropek) do tego katalogu. Jeśli były dwa pliki, pierwszy plik mógł zastąpić drugi plik.
Oto kilka demonstracji:
Więcej niż dwa pliki, a ostatnim argumentem jest plik
Więcej niż dwa pliki, a ostatnim argumentem jest katalog
Dwa pliki
Dalsze wyjaśnienia
Powłoka rozszerza glob (
*
) na argumenty dlamv
. Glob jest zwykle rozwijany w kolejności alfabetycznej.mv
zawsze widzi listę plików i katalogów. Nigdy nie widzi samej globu.Polecenie
mv
obsługuje dwa typy przenoszenia. Jednym jestmv file ... directory
. Drugi tomv old-file-name new-file-name
(lubmv old-file-name directory/new-file-name
).źródło
Najpierw stworzę bazę testową - 5 plików i jeden folder:
Następnie uruchomię polecenie testowe. Ta
-v
opcja określa, że chcę, aby każde polecenie wykonywane przez powłokę było drukowanestderr
. Ta-x
opcja określa, że chcę to samo wydrukowaćstderr
- ale chcę, aby zrobiono to po ocenie polecenia, ale przed uruchomieniem go przez powłokę.WYDAJNOŚĆ
Widzicie więc, że po poleceniu, które karmię powłokę,
echo mv *
po poleceniu, które wykonuje powłoka po*
rozwinięciu,echo mv
następują wszystkie pliki i folder.Domyślnie powłoka rozwija globusy, takie jak:
WYDAJNOŚĆ
Wynika to z
set [+-]f
funkcji glob:WYDAJNOŚĆ
Kiedy więc uruchomisz polecenie w powłoce skonfigurowanej z domyślnymi opcjami, takimi jak
mv *
powłoka, rozwija się do*
słowa lista argumentów wszystkich plików w bieżącym katalogu posortowana według ustawień regionalnych. Wykonuje syscallexec(ve)
dlamv
(zasadniczo) z dołączoną listą argumentów.mv
Otrzymuje więc wszystkie argumenty, gdy powłoka je globalizuje i sortuje. Oprócz robieniastrace
tych efektów, możesz ponownie użyć debugowania w następujący sposób:WYDAJNOŚĆ
I przenośnie:
WYDAJNOŚĆ
Zasadniczo powłoka jest wykonywana
mv
z zawartością katalogu (jeśli nie jest pusty i nie zawiera plików / folderów o nazwach rozpoczynających się od.
) jako listy argumentów.mv
POSIX jest określony interpretować jako ostatecznego argumentu katalogu, jeśli jest ona wywoływana z więcej niż dwóch argumentów - w ten sam sposóbln
jest (bo w rzeczywistości są one bardzo podobne narzędzia w funkcji bazowych) .Wystarczająco dużo
echo
:WYDAJNOŚĆ
Wszystkie pliki zostały przeniesione do ostatniego argumentu - ponieważ jest to folder. Co teraz, jeśli nie jest to folder?
WYDAJNOŚĆ
Tak określa POSIX
mv
w takim przypadku:Więc jeśli
*
rozwija się do:dwa pliki
renamed
do drugiego po drugimunlinked
.jeden lub więcej plików, a następnie ostatni katalog lub link do jednego
coś jeszcze
źródło
sh
rzeczy, zapomniałem o debugowaniu z tym, ale jeśli chodzi o moje oryginalne pytanie, oznacza to, że problemem nie jest powłokamv
? To paskudne, jest prostsze niż początkowo myślałem, ale to prawdziwa pułapka.*
to nie pojedynczy argument? Dobrze? :)Najpierw powłoka rozszerza się
./*
na wszystkie pliki w bieżącym katalogu (z wyjątkiem plików zaczynających się od kropki).mv
niemv
zawodzi.źródło
echo ./*
i zobaczyć, jakiej kolejności używa twoja powłoka (zwykle alfabetycznie).mv
zwraca komunikat o błędzie, jeśli jest wywoływany tylko z jednym argumentem.missing destination file operand after *filename*
choć wczoraj tak nie było.Podczas pisania
mv ./*
powłoka rozwija się./*
przed uruchomieniemmv
.Kilka rzeczy do zapamiętania:
./*
zostanie rozwinięte do mniej niż 2 argumentówmv
, logicznie spowoduje błąd../*
zwykle rozwija się do każdego pliku (w tym katalogu) obecnego w bieżącym katalogu i nie zaczyna się od kropki../*
rozwija, czytając dokumentację swojej powłoki (man 7 glob
jest punktem wejścia do tematu). Różne muszle będą miały różne opcje.źródło
Oto krótsza odpowiedź:
Powłoka rozwija symbol wieloznaczny
*
do listy zawartości katalogu. Następnie powłoka przekazuje tę pełną listę do polecenia. Polecenie nigdy nie widzi*
.Polecenie
mv file1 file2 ... filen directory
przeniesie plik1 ... filen do katalogu.Przykład
Tutaj tworzę katalog testowy zawierający trzy pliki
Nie można przenieść wielu plików do jednego pliku
Dodajmy podkatalog
Państwo może przenieść wiele plików w subdiretory
źródło
mv file1 file2 ... filen directory
jest bardzo mało prawdopodobne, aby w ogóle mieć nic wspólnego z*
.*
się,file dir
chyba że istnieją jakieś ustawienia regionalne, w którychd
następujef
.a b c d
który nie jestfile ... dir
. I tylko komentuje w ogóle, ponieważ nie wspominając o porządek wszędzie, a tylko powiedzieć, że*
staje sięfile ... dir
co nie stało.