Tak głupie niecierpliwe, że użyłem następującego skryptu na moim serwerze 19.04, próbując przenieść kilka plików wideo do folderów z prefiksami:
dirs=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
shopt -s nocasematch
for file in *
do
for dir in "${dirs[@]}"
do
if [ -d "$file" ]; then
echo 'this is a dir, skipping'
break
else
if [[ $file =~ ^[$dir] ]]; then
echo "----> $file moves into -> $dir <----"
mv "$file" "$dir"
break
fi
fi
done
done
Nie mam pojęcia, gdzie poszło nie tak, ale zamiast przenieść pliki do folderów, przeszedł do pojedynczego wyjścia .. więc:
----> a1.ts moves into -> A <----
----> a2.ts moves into -> A <----
----> a3.ts moves into -> A <----
----> a4.ts moves into -> A <----
----> a5.ts moves into -> A <----
----> c1.ts moves into -> C <----
----> c2.ts moves into -> C <----
----> c3.ts moves into -> C <----
----> c4.ts moves into -> C <----
----> c5.ts moves into -> C <----
Na szczęście zatrzymałem proces (CTRL + C), gdy tylko zauważyłem, że nie idzie zgodnie z przeznaczeniem i nie przejrzałem całego folderu.
Więc teraz mam te pliki A
i C
, które są mniej niż GB, i wygląda na to są wideo pojedynczym.
W całkowitym wykorzystaniu dysku przez sam folder nie jest uwzględnione 50 Gb, ale ogólna przestrzeń dyskowa komputera pozostała taka sama. Sprawiasz, że myślę, że pliki nie zostały usunięte?
Każda pomoc doceniona, dziękuję :)
Edycja: pliki faktycznie zniknęły, pozostaje tylko ostatni plik do zapisania, wystarczyło trochę czasu, aby zaktualizować informacje o użyciu dysku.
źródło
A
,B
i tak dalej istniała przed uruchomieniem skryptu? Jeśli nie, po prostu zmieniłeś nazwy plików. Wszystkie pliki, których nazwy zaczynały się oda
lub których nazwaA
została zmienionaA
, więc przetrwał tylko ostatni plik o zmienionej nazwie, pozostałe są zastępowane. Wywołanie zmiennejdir
nie tworzy katalogu!mv "$file" "$dir/"
, z końcem/
; to jeśli$dir
nie istnieje,mv
wystąpi błąd zamiast zmiany nazwy$file
na$dir
. Weź również pod uwagęmv -i
imv -n
. I zawsze rób tomkdir -p
przed przeprowadzką, na wszelki wypadek.Odpowiedzi:
Myślę, że to jest problem: powinieneś utworzyć katalogi A, B, C ... Z. Jeśli tak,
mv
polecenie powinno przenieść pliki do tych katalogów.Ale jeśli nie,
mv
polecenie przenosi pliki do plików o tych nazwach, A, B, C ... i myślę, że to właśnie zrobiłeś.Aby uczynić shellscript bezpieczniejszym, powinieneś stworzyć katalogi (jeśli jeszcze ich nie ma) przed rozpoczęciem przenoszenia.
Jeśli chcesz, aby wszystko stało się jeszcze bezpieczniejsze, możesz również użyć
mv
tej-i
opcjiźródło
touch
byłoby dobrym zamiennikiem, abymkdir
uniknąć konfliktów w przypadku wielokrotnego uruchamiania skryptu?touch
tworzy plik, jeśli nazwa nie istnieje. Więc nie zrobi tego, co chcesz w tym przypadku.mkdir -p
poradzi sobie z użyciem skryptu kilka razy.mv
bezpieczniej jest dostać w zwyczaju dodanie ukośnika do nazwy docelowej, gdy cel jest katalogiem czylimv "$file" "$dir/"
@ Sudodus już wyjaśnił, co poszło nie tak, ale tutaj jest następna prostsza wersja skryptu na następny raz:
Wyjaśnienie
for letter in {a..z}; do
:{a..z}
rozwija się do wszystkich małych liter międzya
iz
:Spowoduje to iterację wszystkich małych liter, zapisując każdą z nich jako
$letter
.dir=${letter^}
: składnia${var^^}
zwraca zawartość zmiennej$var
z pierwszym znakiem wielkimi literami (ponieważ ma tylko jeden znak, to wszystko, czego potrzebujemy). Tak więc, jeśli$letter
jesta
, to${letter^^}
jestA
, a zatem$dir
będzie wersją bieżącej dużej litery$letter
.mkdir -p -- "$dir"
: utwórz katalog. Jeśli już istnieje, nie rób nic (-p
).--
Oznacza koniec opcji i jest przydatna do ochrony przed nazwach zaczynających się-
.mv -- "$letter"* "${letter^}"* "$dir"
: przenieś każdy plik (lub katalog) do odpowiedniego celu.Problem polega na tym, że przenosi także wszystkie katalogi, które możesz mieć. Nie przeniesie katalogów docelowych, ponieważ albo jeszcze nie istnieją, albo spróbujesz przenieść je do siebie, ale wszelkie istniejące katalogi, które nie są katalogiem docelowym, zostaną przeniesione.
Jeśli to jest problem, będziesz musiał zrobić coś takiego:
źródło
${letter^}
i${letter^^}
, a jeśli są identyczne, to po co używać${letter^^}
zamiast$dir
?${var^}
wielką literą tylko pierwszą literę, a${var^^}
wszystkie wielkie litery. Nie ma tu znaczenia, ponieważ$letter
ma tylko jedną literę.$dir
wmv
poleceniu. (W obecnej formie nie powiedzie się, jeśli plik istnieje z pojedynczą wielką literą)Zamiast sprawdzać każdy plik w tablicy słownikowej, która tworzy dużo iteracji, możesz dopasować pliki do wzorców.
Bardzo podstawowy rodzaj:
źródło
Zabezpiecz w swoim .bashrc:
źródło
-n Do not overwrite an existing file. (The -n option overrides any previous -f or -i options.)
więc czy to ważne, że tag -n będzie przed następującymi tagami? W --backup = numerowane będą tworzyć podwójne każdego prawa, a nie, że trochę przesadą (przestrzeń i energia / czasochłonne) gdy ma do czynienia z plikami wideo uber-duży (rozmawiających terabajtów) jest. Dzięki !Dla przypomnienia, kilka sposobów, aby przestać
mv
zastępować istniejące pliki:Jeśli chcesz przejść do katalogu, dodaj ukośnik do celu, tzn. Użyj
mv "$file" "$dir"/
zamiastmv "$file" "$dir"
. Jeśli$dir
nie istnieje lub nie jest katalogiem,mv
narzeka:Wydaje się, że wywołuje
rename("a", "z/")
to wywołanie systemowe , więc powinno być bezpieczne od luk w zabezpieczeniach od czasu sprawdzenia do czasu użycia, na wypadek, gdyby ktoś obsługiwał ten sam zestaw plików w tym samym czasie.Alternatywnie użyj
mv -t "$dir" "$file"
. Znów będzie narzekać, jeśli$dir
nie jest katalogiem.Użyj
-n
opcji, aby zapobiec zastąpieniu istniejących plików:Nie powstrzyma go przed zmianą nazwy pierwszego pliku, ale nie usunie go z innymi.
To wydaje się nazwać zwykłym
rename()
, więc może nie być bezpieczne przy jednoczesnej obsłudze. (Jestrenameat2()
taki, który obsługiwałby flagę, aby zapobiec zastąpieniu).źródło
Chociaż najwyraźniej tak nie jest, możliwe, że możesz to zrobić i nie stracić plików. Wymagałoby to jednej z dwóch rzeczy:
Uniksowe systemy plików pozwalają, aby więcej niż jedna pozycja katalogu odnosiła się do dokładnie tej samej zawartości pliku . Nazywa się to „ twardym linkiem ”. Możesz tworzyć twarde linki za pomocą
ln
polecenia, bez opcji common-s
(soft / symbolic). Tak długo, jak istnieje przynajmniej jedno twarde łącze do zawartości pliku, nie będzie ono ponownie wykorzystywane przez system plików.(Uwaga dodatkowa: uprawnienia zwykle dotyczą zawartości pliku, a nie pozycji katalogu. Dlatego zwykły użytkownik może czasami usunąć plik będący własnością
root
, ale nie może do niego zapisać. Operacja usuwania modyfikuje folder, a nie sam plik. )System plików również nie będzie ponownie używał zawartości pliku, dopóki przynajmniej jeden proces ma otwarty plik. Nawet jeśli nie istnieje pozycja katalogu, system plików nie uzna, że miejsce jest wolne, dopóki żadne procesy nie zostaną otwarte. Plik można odzyskać z wirtualnego systemu plików
/proc/<pid>/fd
,root
dopóki plik jest otwarty. (Dzięki @fluffysheap.)źródło