як порівнювати 2 списку файлів з однаковими іменами файлів, крім розширення a видалити тільки відповідає скрипту оболонки


-2

для кожного файлу .ext1я генерую другий файл .ext2з тим же ім'ям файлу, крім розширення, а потім я видаляю всі .ext1файли. Іноді процес може бути невдалим, тому я хотів би не знати, як видалити лише ті .ext1файли, які мають їх .ext2аналог. Я хочу щось подібне:

#!/bin/bash

ext1s=$(ls -l *.ext1 2>/dev/null | wc -l)
if [ $ext1s -ge 0 ]; then
  generates .ext2 files
  ext2s=$(ls -l *.ext2 2>/dev/null | wc -l)
  if [ $ext1s -eq $ext2s ]; then
    rm *.ext1
  else
    what i need
  fi
else
  echo no .ext1 files
  exit
fi

Для початку $ext1не визначено. Запустіть свій сценарій через ShellCheck
DavidPostill

Відповіді:


0

Просто повторіть *.ext2файли та видаліть відповідний .ext1файл, якщо він існує.

for f in *.ext2;do rm -f "$(basename "$f" .ext2).ext1";done

basenameне тільки витягує ім'я файлу з повного шляху, але також видалить розширення, якщо воно надається другим аргументом, тому "$(basename "$f" .ext2).ext1"видаляє .ext2розширення та замінить його .ext1.

-fу режимі rmзберігає мовчати, якщо .ext1файл не існує.

Версія, що не має базової імені, це:

for f in *.ext2;do rm -f "${f%.ext2}.ext1";done

приємне рішення, воно більш ефективне, ніж моє ... дякую!
kurokirasama

0

Я отримав рішення, якщо є кращий спосіб зробити це, будь ласка, поділіться.

#!/bin/bash

ext1s=$(ls -l *.ext1 2>/dev/null | wc -l)
if [ $ext1s -ge 0 ]; then
  generates .ext2 files
  ext2s=$(ls -l *.ext2 2>/dev/null | wc -l)
  if [ $ext1s -eq $ext2s ]; then
    rm *.ext1
  else
    list=$(comm -12 <(find *.ext1 -type f -exec bash -c 'basename "${0%.*}"' {} \; | sort) <(find *.ext2 -type f -exec bash -c 'basename "${0%.*}"' {} \; | sort))
    for file in $list ; do
      rm $file.ext1
    done
  fi
else
  echo no .ext1 files
  exit
fi

0

Мені не подобається використання непотрібних зовнішніх програм і, як наслідок, накладних витрат: плани запитання вирішувача ls(двічі), wc(двічі), find(двічі) comm, bash(двічі), basename(двічі) та sort(двічі).

Нічого з цього не потрібно: всі вони можуть управляти bashвнутрішніми органами : -

for f in *.ext1
do   if [ "$f" == "*.ext1" ]
     then echo no files
     elif [ -e "${f%.ext1}.ext2" ]
     then rm "$f"
     else
          # Insert here the code to create the .ext2 file from "$f"
     fi
done

Якщо жоден файл не відповідає, *.ext1тоді fбуде встановлено це єдине значення; інакше цикл пройде для кожного відповідного файлу. (Примітка. Якщо ви досить злі, щоб створити файл з буквальним ім'ям *.ext1, то перевірка "немає файлів" не вдасться.)

Для кожного .ext1файлу .ext2перевіряється наявність відповідного файлу: якщо він існує, .ext1видаляється; в іншому випадку код створюється для створення .ext2файлу (необов'язково, якщо це вдалося, оригінальний .ext1файл можна видалити, уникаючи майбутніх зайвих .ext1файлів).


це гарна відповідь, але він має той самий недолік, що і мій, він зациклюється на файлах .ext1 ...
kurokirasama

@ LuisGómezGuzmán - Я зрозумів, що ви хочете перетворити будь-які необроблені .ext1або видалити будь-які оброблені .ext1файли , тому сценарій проходить цикл через усі файли, які він знайде. Де вада?
АФХ

Привіт, я не дуже добре себе виразив. Це не вада. Видалення виконується після генерації .ext2файлів. Отже, циклічно на .ext1файлах і перевірте, чи .ext2існує файл, тоді видаліть це найменш оптимально, ніж цикл на .ext2файли та видаліть .ext1файл (не перевіряйте, так ні, якщо умова).
kurokirasama

@ LuisGómezGuzmán - Ваш оригінальний скрипт містить рядок generates .ext2 files, який я взяв за псевдо-код, щоб вказати, що ви хочете конвертувати .ext1файли в сценарії, чого ви не можете зробити, якщо сканувати лише .ext2файли. Якщо ви хочете видалити лише перетворені .ext1файли, то, звичайно, ефективніше сканувати лише .ext2файли, але я не читаю ваші вимоги.
AFH

Я бачу. У будь-якому разі, я маю на увазі інші способи використання вашої відповіді. Дякую.
kurokirasama
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.