Если имена каталогов _.LD _RESULTS точно содержат имя родительского каталога, то этот цикл for
должен помочь:
for dir in *_*_GeneSet
do
echo cp "$dir"/*.txt "$dir"/_.LD_RESULTS_"$dir"/
done
Я использовал шаблон для подстановочного знака цикла for
, который требует "что угодно", подчеркивание, "что угодно", подчеркивание, "GeneSet" в качестве имени родительского каталога. Отрегулируйте это, чтобы расширить или сузить сферу по мере необходимости.
Если вы планируете использовать имена файлов, найденные любым из приведенных ниже вариантов, убедитесь, что вы не анализируете имена файлов из вывода . Вместо этого замените 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
рекурсивно передает существующие имена путей из текущего каталога или любого из его подкаталогов.
Это работает для меня:
find. -not -name '*.webp' -exec test ! -r {}.webp \; -exec echo {} \;
Он находит все имена, которые не заканчиваются на .webp
. Для каждого найденного имени проверяется, существует ли файл с таким же именем и расширением .webp
. Если нет, то он печатает файл.
Важно отметить, что второй -exec
выполняется только в случае успешного возврата первого, то есть только в том случае, если соответствующий файл с расширением .webp
не существует.
Работая с вашим списком файлов, я вывожу
./filename-600x600.jpg
./filename-150x150.jpg
Попробуйте это с циклом:
# 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
nullglob If set, Bash allows filename patterns which match no files to expand
to a null string, rather than themselves.