Да, в оболочке bash
вы можете использовать замену процесса:
minimap -ax map-ont /path/to/fasta.file <( cat *.fastq ) >output.sam
<(... )
— это подстановка процесса. Он будет заменен именем пути именованного канала (что-то вроде /dev/fd/XXX
), который будет производить вывод команды внутри при чтении из него. Вывод команды в процессе подстановки не сохраняется на диске.
Пока инструменту minimap
не нужно прыгать назад и вперед по данным fastq, а просто считывать их последовательно, это, вероятно, будет работать.
Делая это без замены процессов (это также будет работать с sh
или любой оболочкой POSIX):
mkfifo fastq_data
cat *.fastq >fastq_data &
minimap -ax map-ont /path/to/fasta.file fastq_data >output.sam
rm fastq_data
Это почти то же самое, что и первая команда. Он создает именованный канал и объединяет с ним данные fastq (, cat
работает как фоновое задание, пока весь его вывод не будет прочитан minimap
, а затем завершается ). Затем вызывается инструмент minimap
с именованным каналом для данных fastq. Когда это будет сделано, именованный канал будет удален.
Чтение из канала fastq_data
означает чтение напрямую из команды cat
, а не из какого-то временного файла. Опять же, результат cat
никогда не сохраняется на диске.
Если инструменту minimap
по какой-то причине требуется файл fastq с определенным суффиксом имени файла, это может быть лучшим вариантом. Просто назовите свой именованный канал как data.fastq
или аналогичный.
Шаг 1. )Создайте список всех применимых каталогов, отсортируйте его в алфавитно-цифровом порядке и убедитесь, что нет дубликатов. Сохраните список во временном файле:
find /work/user/folder1/ [...] -type d | sort | uniq > all_directories.txt
Шаг 2. )Создайте список всех *.grid
файлов.
find /work/user/folder1/ [...] -name *.grid > grid_files.txt
Шаг 3. )Проработайте список *.grid
файлов, возьмите имя каталога каждого файла и снова убедитесь, что нет дубликатов:
while read FILENAME
do
echo $(dirname "$FILENAME")
done < grid_files.txt | sort | uniq > dirs_with_gridfiles.txt
Шаг 4. )Запустите эти два списка вместе и снова отсортируйте результат. Теперь каталоги с *.grid
файлами должны быть перечислены ровно дважды каждый, а каталоги без *.grid
файлов ровно один раз каждый. Таким образом, вы можете указать uniq
сообщать только о неповторяющихся -строках:
cat all_directories.txt dirs_with_gridfiles.txt | sort | uniq -u > dirs_with_no_gridfile.txt
Вот и получишь.
Используйте find
для вызова find
!
find. -type d \( -exec sh -c 'cd "$0"; find. \( -name. -o -prune \) -name "*.grid" | grep -q.' {} \; -o -print \)
Это соответствует стандарту POSIX -, благодаря этому ответу:
Кроме того, это будет работать независимо от пробелов, специальных символов или даже новых строк в именах файлов или каталогов.:)
(Н.Б. :Если у вас есть специальные символы или новые строки в именах ваших каталогов, вы должны изменить этот последний -print
первичный на любое действие, которое вы хотите выполнить с каталогами, поскольку вы не сможете безопасно разобрать получившийся напечатанный список, если вы просто используете -print
.)
Вот версия с разрывами строк, добавленными в возможно ошибочной попытке улучшить читабельность:
find. -type d \
\( \
-exec sh -c '
cd "$0";
find. \( -name. -o -prune \) -name "*.grid" |
grep -q.
' {} \; \
-o -print \
\)
Если у вас Bash v4 (или выше ), я думаю, вы также можете сделать это с помощью одного цикла, ищущего все *.grid
файлы, плюс один внутренний цикл для всех каталогов, чтобы перечислить, в каких каталогах есть файлы, а в каких не надо. В Bash v4 мы используем одну из его опций, которая обычно отключена.
(
# 'globstar' enables '**' expansions, which instructs
# the shell to search all and below recursively
shopt -s globstar
# Note that '**' is implicitly recursive, no need to specify
# depth. If you do want to specify precise depth, then use a
# '*/' for each wanted depth, like '*/*/*/' for 3 depths
for f in /work/user/folder1/**/*.grid; do
f="${f##*/}" # strip directory from found name
printf '\nNow looking for: %s\n' "$f"
# A simple '**/' returns directories only
for d in /work/user/folder1/**/; do
# simple existence test
[ -e "${d}${f}" ] && \
printf ' present in %s\n' "$d" || \
printf 'not present in %s\n' "$d"
done
done
)
К сожалению, синтаксис **
не соответствует POSIX.
Однако, если вы знаете точную глубину поиска, просто уберите команду shopt
и превратите каждый **/
в точную глубину, выраженную как */
повторений, и это должно хорошо работать и в оболочках POSIX..