Як видалити всі файли в папці, крім лише вказаних файлів?


11

Я хочу видалити всі файли в каталозі, залишаючи лише вказані файли, вони не мають нічого спільного за назвою. Як я міг цього досягти?

Наприклад, імена файлів, які я хочу зберегти, це:

file_1.png, another_file.jpg,some_music.mp3

Відповіді:


15

Якщо ви використовуєте bash:

shopt -s extglob
rm -- !(file1|file2|file3)

Перший рядок просто активує розширене узгодження шаблону, а після цього ми використовуємо один із них:

!(pattern-list) відповідає будь-якому, крім однієї із заданих шаблонів

а список шаблонів - це список одного або декількох шаблонів, розділених a |.


Або з zsh

setopt extendedglob
rm -- ^(file1|file2)

Або, більш портативний, використовуючи find:

find . -maxdepth 1 ! -name 'file1' ! -name 'file2' -type f -exec rm -v {} +

3
Можливо, буде корисно включити, як повернути необов'язкове поведінку оболонки назад ( shopt -u extglob).
geedoubleya

7

Зробіть підкаталог tmp, перемістіть усі файли, які ви хочете зберегти, до цього каталогу та виконайте rm -f *згодом. Це не вплине на tmpкаталог.

Після цього просто зробіть:

mv tmp/* .
rmdir tmp

(Якщо припустимо, що жоден із файлів, які ви перемістили, починається з крапки).

Це один з небагатьох випадків, коли є сенс використовувати мишу та браузер файлів, як Nautilus, де ви можете насправді - Ctrlнатиснути кілька файлів, які ви хочете зберегти, а потім скористатися меню: Edit -> Invert Selectionотримати інші файли, а потім видалити ці .


переміщення файлів у каталог tmp звучить приємно. У будь-якому разі, я повинен це робити з командного рядка. Спасибі!
AGamePlayer

3
@AwQiruiGuo Tmp має перевагу в тому, що він спочатку розділяє файли на два набори, перш ніж безповоротно видалити ті, які вам не потрібні. Таким чином, ви можете запустити, lsщоб побачити, чи не пропустили жодного з файлів, які хочете зберегти.
Антон

2

Додайте назви файлів, які ви хочете зберегти, у текстовий файл, по одному на рядок. Цей файл не повинен бути в каталозі, або ви також повинні додати його ім'я.

Якщо ім'я вашого каталогу foo, а ім'я файлу - бар , зробіть наступне.

find foo -type f -print0|grep -vzZ -f bar|xargs -0 rm

Це робить наступне:

  1. find -type fшукає імена всіх файлів у foo та його підкаталогах та друкує їх у STDOUT. З опцією -print0він розмежовує назви файлів з байтами NUL.
  2. grep -v -f barвиключає всі назви файлів, які відповідають рядку в рядку . З опцією -zвін розглядає свій вхід як набір рядків, розмежованих на байт NUL, а з опцією -Zвін розмежовує свій вихід на байт NUL.
  3. xargs rmrmкілька разів закликає видалити файли. З опцією -0він розглядає свої дані як набір рядків, розділених на байт NUL.

Це працює з назви файлів, що містять пробіл.


Це не працюватиме, оскільки назви файлів можуть містити нові рядки.
Антон

@Anthon змінив параметри пошуку, grep, xargs, щоб впоратися з іменами файлів, що містять пробіли, включаючи новий рядок
Mathias Weidner

Якщо ви хочете скористатись, findя б краще зробивfind . -maxdepth 1 ! -name 'file1' ! -name 'file2' -type f -exec rm -vi {} +
jimmij
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.