Napisałem skrypt, aby przenieść niektóre pliki z jednego folderu do innego, ale dostałem następujący błąd, sprawdziłem 2 foldery i zauważyłem, że w jednym folderze są takie pliki, a w innym nie ma takich plików, ale dlaczego wszystkie pokazują „mv nie można stat Brak takich plików lub katalogu ”
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/194.199.68.165_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/194.42.17.124_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/195.113.161.13_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/203.159.127.3_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/212.199.61.205_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/212.51.218.235_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/213.73.40.105_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/41.225.7.4_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/83.230.127.122_tcp.folder/data/*': No such file or directory
[esolve@kitty tcp_50x50]$ ls /home/wgong/project/capture/tcp_50x50/dest_folder/194.199.68.165_tcp.folder/
[esolve@kitty tcp_50x50]$ ls /home/wgong/project/capture/tcp_50x50/dest_folder/203.159.127.3_tcp.folder/data/
129.88.70.226 132.187.230.1 138.96.116.22 155.185.54.250 192.38.109.144 193.136.227.163 193.175.135.61 195.113.161.13 83.230.127.122
130.104.72.200 132.227.62.122 147.83.29.232 156.17.10.52 192.42.43.22 193.137.173.218 193.205.215.74 212.199.61.205
131.130.69.164 132.252.152.194 148.81.140.193 157.181.175.249 192.43.193.71 193.144.21.131 193.226.19.30 212.51.218.235
131.188.44.102 134.151.255.180 152.66.245.162 160.78.253.31 193.1.170.136 193.145.46.243 194.199.68.165 213.73.40.105
131.254.208.10 138.48.3.203 152.81.47.4 192.114.4.3 193.136.166.56 193.166.160.98 194.42.17.124 41.225.7.4
skrypt jest:
list=`ls dest_folder`
cd dest_folder
cwd=`pwd`
for folder in $list;do
mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}
done
Wpadłem /home/esolve/project/capture/tcp_50x50/
-r
domv ${cwd}/${folder}'/data/*' ${cwd}/${folder}
?-r
opcji dlamv
Odpowiedzi:
Cytaty (
'
) uniemożliwiają powłoce wykonywanie globowania.*
Przekazywana jest dosłownie domv
komendy, która nie, ponieważ nie znajdują się pliki zwane*
w katalogach wskazanych.Zmień to na:
(Podwójne cudzysłowy, aby zapobiec problemom, jeśli kiedykolwiek masz nazwę katalogu ze spacjami.
*
Poza cudzysłowami).Nadal będziesz otrzymywać błędy dla pustych katalogów. (Taki sam powód: jeśli plik nie znajdzie dopasowania do wzorca, przekazuje sam wzorzec jako argument do polecenia).
źródło
*
poza cytatami?Twój kod ma kilka problemów:
Przechowujesz wynik
ls
bez końcowych znaków nowego wiersza w$list
.ls
wyświetla listę nazw plików oddzielonych znakami nowego wiersza.newline
jest tak samo poprawnym znakiem, jak każdy w nazwie pliku, więc nie można w niezawodny sposób wykorzystać danych wyjściowych. Na przykład danels
wyjściowe dla katalogu, który zawieraa
ib
jest taki sam, jak dla katalogu zawierającego jeden plik o nazwiea<newline>b
.Nie sprawdzasz, czy polecenie się nie powiodło. Zasadniczo powinieneś sprawdzać status wyjścia poleceń, ale jest to szczególnie prawdziwe
cd
, ponieważ pozostałe polecenia zakładają, że jesteś w tym nowym katalogu, a może to mieć dramatyczne konsekwencje, gdy nie jesteś.Powłoki POSIX już utrzymują (jedną) ścieżkę do bieżącego katalogu w
$PWD
zmiennej, więc nie powinieneś używać tego
tutaj (szczególnie w ogólnym przypadku, ponieważ podstawianie poleceń usuwa końcowe znaki nowej linii ze ścieżki). Równieżpwd
mv
akceptuje ścieżki względne, więc nie trzeba budować ścieżki bezwzględnej.Pozostawienie zmiennej bez cudzysłowu to operator split + glob w powłokach. Oznacza to, że zawartość zmiennej jest podzielona (na separatorach wymienionych w
$IFS
specjalnych regułach dla białych znaków), a każdy element wynikający z tego podziału jest szukany znaków wieloznacznych, aby można je było rozwinąć do listy pasujących plików.Tutaj chcesz podziału, ale tylko na znaki nowego wiersza i nie chcesz globowania, więc musisz go wyłączyć:
Ponownie pozostawienie zmiennej niecytowanej to operator split + glob . Tutaj nie chcesz, więc musisz zacytować te zmienne.
Jak już wspomniano, symbole wieloznaczne są rozszerzane tylko wtedy, gdy nie są cytowane, abyś musiał je
*
usunąć z cudzysłowów. Jeśli wcześniej wyłączono globowanie za pomocąset -f
, konieczne będzie przywrócenie goset +f
przed wywołaniem tego polecenia.O wiele lepszym sposobem na napisanie tego byłoby:
Kilka uwag:
data
folderów.-i
opcjęmv
).*/
, zapętlamy tylko katalogi , ale obejmuje to również dowiązania symboliczne do katalogów. Jeśli nie chcesz, musisz dodać[ -L "${folder%/}" ] && continue
wewnątrz pętli.*/
zostanie on rozwinięty do siebie, więc pojawi się komunikat o błędziemv
informujący, że nie można znaleźć pliku o nazwie*/data/*
. Podobnie, jeśli nie ma nie ukrytego pliku w żadnym folderze, pojawi się komunikat o błędzie,that-folder/data/*
który nie istnieje.źródło