Відповіді:
Ось просте рішення, яке ви, ймовірно, повинні використовувати:
mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif
У .keep
розширенні нічого особливого , це просто робить так, щоб ім’я файлу тимчасово не закінчувалося .gif
.
Якщо ви не повинні перейменовувати файл (і є сценарії, коли це важливо):
for X in *.gif; do
if [ "$X" != "filename.gif" ]; then
rm "$X"
fi
done
Або ви можете написати це коротше так:
for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done
Ви можете скористатися find
замість цього; це дуже потужний, ви могли б розглянути його більш зручним для читання, і це краще ручок дивних імен файлів з символами , як *
в них .
find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete
Я використовував -not
оператора для читабельності, але якщо важлива відповідність POSIX - якщо ви не використовуєте GNU find, або якщо це сценарій, який ви маєте намір перерозподілити іншим або запустити в різних системах - вам слід використовувати !
замість оператора:
find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete
Зручна річ у find
тому, що ви можете легко змінити команду на нечутливість регістру, щоб вона знаходила і видаляла файли з розширеннями як .GIF
:
find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete
Зверніть увагу, що я використовував -iname
замість -name
схеми пошуку, *.gif
але я не використовував її filename.gif
. Імовірно, ви точно знаєте, як називається ваш файл, і -iname
буде відповідати альтернативній великій літери не тільки в розширенні , але і в будь-якому місці імені файлу.
Усі ці рішення видаляють лише файли, що знаходяться негайно в поточному каталозі . Вони не видаляють файли, що не містяться в поточному каталозі, і не видаляють файли, що знаходяться в підкаталогах поточного каталогу.
Якщо ви хочете видалити файли скрізь, що містяться в поточному каталозі (тобто в тому числі в підкаталогах і в підкаталогах цих підкаталогів тощо) - файли, що містяться в поточному каталозі або будь-якому з його нащадків), використовуйте find
без maxdepth -1
:
find . -not -name 'filename.gif' -name '*.gif' -delete
Будьте обережні з цим!
Ви також можете встановити інші значення за допомогою -maxdepth
. Наприклад, для видалення файлів у поточному каталозі та його дітей та онуків, але не будь-які глибші:
find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete
Просто переконайтеся, що ви ніколи не ставите -delete
перше, перед іншими виразами! Ви побачите, що я завжди ставив -delete
у кінці. Якщо ви поставите його на початку, воно буде оцінено спочатку, і всі файли в розділі .
(включаючи файли, що не закінчуються, .gif
та файли в глибоких підкаталогах підподібних підрозділів .
) будуть видалені!
Для отримання додаткової інформації зверніться до сторінок довідника bash
і sh
і для команд , які використовуються в цих прикладах: mv
, rm
, [
, і (особливо) find
.
find
, який є дуже універсальним.
find
обробляти дивні назви файлів *
у них, ніж for-loop? Цикл for обробляє файли *
штрафом, оскільки ви використовували подвійні лапки.
Якщо ви використовуєте bash
(оболонка за замовчуванням), extglob
опція оболонки дозволяє використовувати розширений синтаксис відповідності шаблону. Щоб увімкнути це, використовуйте shopt
вбудовану команду:
shopt -s extglob
(Я включаю цей рядок у свій .bashrc
файл.)
Крім усього іншого, він надає доступ !()
оператору, який відповідає будь-якому шаблону, що не знаходиться в межах паролів. Для вашої мети:
rm !(filename).gif
Більш детальна інформація доступна в man bash
розділі "Узгодження шаблонів".
extglob
потрібно включити, але нічого поганого не відбувається, якщо його відключити (у такому випадку це просто не працює). І це, здається, увімкнено за замовчуванням, навіть якщо я не маю shopt -s extglob
жодного з моїх (або глобальних) файлів конфігурації. Якщо є просте пояснення, чому це працює для мене поза коробкою, ви можете додати його до цієї відповіді; або я можу поставити нове запитання.
Відкрийте термінал з Ctrl+ Alt+ Tі введіть:
find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;
Різниця між -delete
і -exec rm -vf {} \;
полягає в тому, що з другого варіанту ви зможете побачити, які файли було видалено через -v
прапор. Це те, що неможливо зробити з -delete
опцією. ( -name -delete
буде надруковано імена файлів, але rm
з -v
виявленням, чи вдало видалено кожен файл .)
Там є GLOBIGNORE
змінна. Від man bash
:
GLOBIGNORE
A colon-separated list of patterns defining the set of filenames
to be ignored by pathname expansion. If a filename matched by a
pathname expansion pattern also matches one of the patterns in
GLOBIGNORE, it is removed from the list of matches.
Таким чином, простий спосіб - просто встановити GLOBGINORE
вказане ім'я файлу:
$ touch {a,b,c,d}.png
$ echo *.png
a.png b.png c.png d.png
$ GLOBIGNORE=c.png
$ echo *.png
a.png b.png d.png
Отже, у вашому випадку:
GLOBIGNORE=filename.gif; rm *.gif
Звичайно, оскільки GLOBIGNORE
містить шаблони, ви можете користуватися нею, коли потрібно виключити шаблон:
$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.png
Перевагою (?!) GLOBIGNORE
Є те, що це.
..
налаштування автоматично виключає та не відповідає, і це дозволяє dotglob
:
The GLOBIGNORE shell variable may be used to restrict the set of file‐
names matching a pattern. If GLOBIGNORE is set, each matching filename
that also matches one of the patterns in GLOBIGNORE is removed from the
list of matches. The filenames ``.'' and ``..'' are always ignored
when GLOBIGNORE is set and not null. However, setting GLOBIGNORE to a
non-null value has the effect of enabling the dotglob shell option, so
all other filenames beginning with a ``.'' will match. To get the old
behavior of ignoring filenames beginning with a ``.'', make ``.*'' one
of the patterns in GLOBIGNORE. The dotglob option is disabled when
GLOBIGNORE is unset.
Отже, простий спосіб видалення всіх файлів і папок у каталозі:
GLOBIGNORE=.; rm -r *
Ім'я *
буде відповідати назви файлів, починаючи з .
, оскільки воно GLOBIGNORE
ввімкнено dotglob
, але воно не збігається .
або ..
, таким чином, ви не вплинете на батьківський каталог таким чином.