Нужен способ поиска отсутствующих файлов

Если имена каталогов _.LD _RESULTS точно содержат имя родительского каталога, то этот цикл forдолжен помочь:

for dir in *_*_GeneSet
do
  echo cp "$dir"/*.txt "$dir"/_.LD_RESULTS_"$dir"/
done

Я использовал шаблон для подстановочного знака цикла for, который требует "что угодно", подчеркивание, "что угодно", подчеркивание, "GeneSet" в качестве имени родительского каталога. Отрегулируйте это, чтобы расширить или сузить сферу по мере необходимости.

0
11.03.2021, 09:58
3 ответа

Если вы планируете использовать имена файлов, найденные любым из приведенных ниже вариантов, убедитесь, что вы не анализируете имена файлов из вывода . Вместо этого замените printfлюбой операцией, которую вам нужно выполнить . Таким образом, вы избежите проблем с именами файлов, которые содержат пробелы, символы подстановки и т. д. Это также сделает ваш код более эффективным и красивым и в конечном итоге приведет к более здоровому образу жизни и более хорошим друзьям.

См. Почему зацикливание вывода find является плохой практикой?

Я делаю предположение, что вы хотели бы найти изображения JPEG, которым не соответствует файл .webp, потому что вы хотите создать файлы .webp. Вот почему я использую тест-e("имя существует" )ниже, а не-f("имя существует и является обычным файлом или символической ссылкой на такой файл" )или-r("имя существует и доступен для чтения" ).

Если .webpимя существует , и если это каталог, специальный символьный файл или какой-либо другой не -обычный тип файла (, тест -fбудет false ), или если он не читается (, тест -rбудет ложным ), будет проблематично создать файл .webp, так как он перезапишет что-то существующее или будет помещен в каталог, или вызвать ошибку разрешения, в зависимости от того, как был создан этот файл .webp.


Использование простого цикла, который перебирает совпадающие имена *.jpgи выводит те имена, которые не соответствуют *.jpg.webpфайлу:

for name in *.jpg; do
    [ -f "$name" ] && [ ! -e "$name.webp" ] && printf '%s\n' "$name"
done

Чтобы сохранить имена в списке, мы можем использовать список позиционных параметров:

set --
for name in *.jpg; do
    [ -f "$name" ] && [ ! -e "$name.webp" ] && set -- "$@" "$name"
done

printf 'Needs webp fixed: %s\n' "$@"

В bashвы можете сохранить имена в именованном массиве:

needs_webp=()
for name in *.jpg; do
    [ -f "$name" ] && [ ! -e "$name.webp" ] && needs_webp+=( "$name" )
done

printf 'Needs webp fixed: %s\n' "${needs_webp[@]}"

В оболочке zshможно было выполнить проверку имени *.webpв самой подстановке:

printf 'Needs webp fixed: %s\n' *.jpg(.e['[ ! -e $REPLY.webp ]'])

Здесь .в квалификаторе подстановки в конце шаблона гарантирует, что сопоставляются только обычные файлы (, а не каталоги и т. д. ), а e['[ ! -e $REPLY.webp ]']действует как проверка, чтобы увидеть, текущее имя, $REPLY, должно быть включено в результирующий список или нет.


Сfind:

find. -name '*.jpg' -type f ! -exec test -e {}.webp \; -print

Это ищет любой обычный файл с именем, соответствующим шаблону *.jpgв текущем каталоге или ниже, а затем печатает это имя, если нет файла, соответствующего тому же имени, но с .webp, добавленным в конец.

Однако,стандарт POSIX не гарантирует, что {}будет заменено текущим именем файла, если оно объединено с какой-либо другой строкой, как показано выше. Поэтому, если вы хотите быть уверены, что это сработает, вы должны сказать

find. -name '*.jpg' -type f -exec sh -c '
    for name do
        [ -e "$name.webp" ] && printf "%s\n" "$name"
    done' {} +

Как видите, теперь мы более или менее вернулись к первому циклу этого ответа. Единственная разница в том, что findрекурсивно передает существующие имена путей из текущего каталога или любого из его подкаталогов.

2
18.03.2021, 22:26

Это работает для меня:

find. -not -name '*.webp' -exec test ! -r {}.webp \; -exec echo {} \;

Он находит все имена, которые не заканчиваются на .webp. Для каждого найденного имени проверяется, существует ли файл с таким же именем и расширением .webp. Если нет, то он печатает файл.

Важно отметить, что второй -execвыполняется только в случае успешного возврата первого, то есть только в том случае, если соответствующий файл с расширением .webpне существует.

Работая с вашим списком файлов, я вывожу

./filename-600x600.jpg
./filename-150x150.jpg
1
18.03.2021, 22:26

Попробуйте это с циклом:

# to expand to null string in empty directories¹
shopt -s nullglob
# loop over the jpg files
for i in *.jpg; do 
  # test if there's a file that matches the name but with '.webp' extension
  # if there's a match don't do anything and continue with the loop
 [[ -f "$i.webp" ]] && continue || \
 # else perform an operation
 echo "$i"
done

filename-150x150.jpg
filename-600x600.jpg

¹ 4.3.2 Встроенный магазин

nullglob

    If set, Bash allows filename patterns which match no files to expand  
to a null string, rather than themselves.
1
18.03.2021, 22:26

Теги

Похожие вопросы