2014-02-18 7 views
2

Я пытаюсь сопоставить файлы резервных копий в скрипте, а затем удалять их. Файлы резервного копирования являются те, которые имеют тильду (~) в них:Сопоставление файлов с резервной копией (`* ~`)

$ ls -al 
drwxr-xr-x 3 jwalton jwalton 4096 Feb 18 09:00 . 
drwxr-xr-x 5 jwalton jwalton 4096 Feb 18 08:54 .. 
drwxr-xr-x 5 jwalton jwalton 4096 Feb 18 08:54 test-proj 
-rwxr-xr-x 1 jwalton jwalton 664 Feb 18 09:00 clean.sh 
-rwxr-xr-x 1 jwalton jwalton 628 Feb 18 08:59 clean.sh~ 

Мой чистый сценарий имеет следующий тест, но, похоже, что я делаю что-то неправильно:

if [ -e "*~" ]; then 
    rm "*~" 
fi 

Что является правильным тестом для соответствия резервному файлу?

+1

Проверьте это, заменив 'rm' на' ls', например. – fedorqui

ответ

5

Это ваши цитаты, которые привинчивают его. Он ищет файл, который буквально называется *~. Это работает, но только если *~ расширяется ровно один файл ::

if [ -e *~ ]; then 
    rm *~ 
fi 

Почему? Поскольку оболочка расширяет подстановочные знаки сначала. Так что, если она не совпадает ни с чем, это эквивалентно:

if [ -e ]; then // false positive! 

Если он соответствует один файл x.txt~, то он расширяется:

if [ -e x.txt~ ]; then // OK 

Если он соответствует более одного файла, x.txt~ y.txt~, то она расширяется :

if [ -e x.txt~ y.txt~ ]; then // "[: x.txt~: binary operator expected" 

Это стоит знать, что UNIX имена файлов могут содержать любые символы, кроме / и ASCII 0. Таким образом, вы можете сделать:

$ touch "*~" 
$ ls "*~" 
*~ 
$ rm "*~" 

И вы можете в конечном итоге с файлами с неуклюжими названиями, такими как -r.

$ touch -- -r # or imagine, your own C, Java etc. program 
$ ls 
-r 
$ rm -- -r 

Однако, if в действительности не требуется. Это только там, чтобы предотвратить ls давать No such file or directory ошибки, и вы можете подавить тех, кто:

rm -f *~ 
+1

'[-e * ~]' будет работать только в том случае, если шаблон расширяется до одного файла; в противном случае вы получите сообщение об ожидаемом двоичном операторе. – chepner

+0

@chepner Отличная точка; добавлен к телу. – slim

7

Вам не нужно, чтобы проверить это. rm -f (игнорирование несуществующих файлов) выполнит эту работу.

rm -f *~ 

Внутри цитате * соответствует * буквально:

Пример:

$ ls 
*~ a a~ 
$ ls *~ 
*~ a~ 
$ ls "*~" 
*~ 
+0

Спасибо falsetru.Причина, по которой я пытаюсь его сопоставить, заключается в том, чтобы избежать сообщения об ошибке «* ~ не найдено». – jww

+2

@noloader, если вы используете опцию '-f',' rm' не выдает ошибку об этом. – falsetru

+1

Это потому, что '~' не расширяется в двойных кавычках. – fedorqui

1

Я думаю, с помощью функции поиска лучше:

find ./ -name "*~" -exec rm {} \; 
+0

'найти. -name "* ~" -print | xargs rm -f' - немного более эффективно. – slim

+1

'найти. -name "* ~" -delete' - еще эффективнее – Biffen

+0

@ Диффен Дох. У меня был grepped 'man find' для' -rm' – slim

1

Если вы хотите рекурсивно спускаться в в подкаталогах:

shopt -s globstar nullglob 
rm **~ 
Смежные вопросы