У вашому сценарії є різні можливі точки відмови. Перш за все, rm *.old*
використовуватиме глобулінг для створення списку всіх відповідних файлів, які можуть мати справу з іменами файлів, що містять пробіли. Однак ваш сценарій присвоює змінну кожному результату глобальної сфери і робить це без цитування. Це порушиться, якщо імена файлів містять пробіл. Наприклад:
$ 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'
Як бачите, цикл не вдався до файлу з пробілами в його імені. Щоб правильно це зробити, вам потрібно буде процитувати змінну:
$ for i in ./*; do oldfile="$i"; rm -v "$oldfile"; done
removed './file name with spaces.old.txt'
removed './file.old.txt'
Це ж питання стосується майже кожного використання $i
вашого сценарію. Ви завжди повинні цитувати свої змінні .
Наступне можливе питання полягає в тому, що ви, здається, очікуєте, що *.old.*
файли збігаються з розширенням .old
. Це не так. Він відповідає "0 або більше символів" ( *
), потім a .
, потім "старий", потім ще один, .
а потім "0 або більше символів знову". Це означає, що він не відповідатиме щось на зразок file.old
, а лише щось на зразок `file.old.foo:
$ ls
file.old file.old.foo
$ for i in *; do if [[ "$i" == *.old.* ]]; then echo $i; fi; done
file.old.foo
Отже, ворог не відповідає file.old
. У будь-якому випадку ваш сценарій набагато складніший, ніж потрібно. Спробуйте це замість цього:
#!/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
Зауважте, що я додав -v
до заяв rm
і cp which does the same thing as what you were doing with your
echo`.
Це не ідеально, оскільки коли ви знайдете, наприклад, file.old
що буде видалено, а пізніше сценарій спробує скопіювати його та вийти з ладу, оскільки файл більше не існує. Однак ви не пояснили, що насправді намагаєтеся зробити сценарій, тому я не можу це виправити, якщо ви не скажете нам, що ви насправді намагаєтесь виконати.
Якщо ви хочете: i) видалити всі файли з .old
розширенням і ii) додати .old
розширення до будь-яких існуючих файлів, у яких його немає, все, що вам потрібно, це:
#!/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.*
який видаляє ці файли але не файл резервного копіювання file.old. Я намагаюся це зробити за своїм сценарієм. Дякую