W twoim skrypcie występują różne możliwe punkty awarii. Przede wszystkim rm *.old*
użyje globowania, aby utworzyć listę wszystkich pasujących plików, które mogą poradzić sobie z nazwami plików zawierającymi białe znaki. Jednak twój skrypt przypisuje zmienną do każdego wyniku globu i robi to bez cytowania. To się zepsuje, jeśli nazwy plików zawierają spacje. Na przykład:
$ ls
'file name with spaces.old.txt' file.old.txt
$ rm *.old.* ## works: both files are deleted
$ touch "file.old.txt" "file name with spaces.old.txt"
$ for i in ./*; do oldfile=$i; rm -v $oldfile; done
rm: cannot remove './file': No such file or directory
rm: cannot remove 'name': No such file or directory
rm: cannot remove 'with': No such file or directory
rm: cannot remove 'spaces.old.txt': No such file or directory
removed './file.old.txt'
Jak widać, pętla nie powiodła się dla pliku ze spacjami w nazwie. Aby zrobić to poprawnie, musisz zacytować zmienną:
$ for i in ./*; do oldfile="$i"; rm -v "$oldfile"; done
removed './file name with spaces.old.txt'
removed './file.old.txt'
Ten sam problem dotyczy prawie każdego użycia $i
skryptu. Powinieneś zawsze cytować zmienne .
Kolejnym możliwym problemem jest to, że wydaje się oczekiwać, że *.old.*
pasuje do plików z rozszerzeniem .old
. Tak nie jest. Dopasowuje „0 lub więcej znaków” ( *
), a następnie a .
, następnie „stary”, następnie inny, .
a następnie „ponownie 0 lub więcej znaków”. Oznacza to, że będzie to nie pasują do czegoś podobnego file.old
, ale tylko coś w rodzaju `file.old.foo:
$ ls
file.old file.old.foo
$ for i in *; do if [[ "$i" == *.old.* ]]; then echo $i; fi; done
file.old.foo
Więc nie ma przeciwnika file.old
. W każdym razie skrypt jest o wiele bardziej złożony niż jest to konieczne. Spróbuj zamiast tego:
#!/bin/bash
for i in *; do
if [[ -f "$i" ]]; then
if [[ "$i" == *.old ]]; then
rm -v "$i" || echo "rm failed for $i"
else
echo "$i doesn't have an .old extension"
fi
cp -v "$i" "$i".old
else
echo "$i is not a file"
fi
done
Zauważ, że dodałem -v
do instrukcji echo rm
i cp which does the same thing as what you were doing with your
.
Nie jest to idealne, ponieważ na przykład, gdy znajdziesz, file.old
że zostanie on usunięty, a później skrypt spróbuje go skopiować i nie powiedzie się, ponieważ plik już nie istnieje. Jednak nie wyjaśniłeś, co skrypt naprawdę próbuje zrobić, więc nie mogę tego naprawić, chyba że powiesz nam, co naprawdę próbujesz osiągnąć.
Jeśli chcesz: i) usunąć wszystkie pliki z .old
rozszerzeniem oraz ii) dodać .old
rozszerzenie do wszystkich istniejących plików, które go nie mają, wszystko czego naprawdę potrzebujesz to:
#!/bin/bash
for i in *.old; do
if [[ -f "$i" ]]; then
rm -v "$i" || echo "rm failed for $i"
else
echo "$i is not a file"
fi
done
## All the ,old files have been removed at this point
## copy the rest
for i in *; do
if [[ -f "$i" ]]; then
## the -v makes cp report copied files
cp -v "$i" "$i".old
fi
done
rm *.old.*
który usuwa te pliki ale nie plik kopii zapasowej file.old. Próbuję to zrobić w moim skrypcie. Dzięki