Ошибка "xargs" в отношении файлов пар и одиночных файлов

.got.pltнеобходим для выполнения вызовов библиотеки (, включая, помимо прочего, вызовыlibc). После того, как вы закончите повреждение этого раздела, любые вызовы libc будут недоступны -.

Если вы запускаете двоичный файл через gdb, вы не должны получить ошибку сегментации в scanf— вы должны получить ошибку сегментации в printf@plt, так как динамический вызов не может быть выполнен с поврежденным .got.pltраздел.

Вы по-прежнему сможете выполнять не -динамические и системные вызовы:

#include <stdio.h>
  __asm(
    "finish:"
        "mov $60, %rax\n"
        "mov $42, %rdi\n"
        "syscall\n"
     );

int gv=10;

int main(){

  char *v=(char*)0x601000;//0x601030
  printf("gv=%p\n", &gv);
  scanf("%s", v);
  _Noreturn void finish(void);
  finish();
  //should exit with 42

  printf("You gave=%s\n", v);

}
1
05.09.2019, 09:04
1 ответ

версия xargs:

Для этого вам нужно разбить каждую строку входного файла на белый -пробел (, что является xargsповедением по умолчанию ), а затем получить xargsдля запуска shscript один раз для каждого слова, используя -n 1. В качестве альтернативы вы можете заставить сценарий оболочки перебирать "$@".

Вы не можете использовать здесь -I {}, потому что это заставляет xargsчитать входной файл по одной строке за раз. Даже если вы установите разделитель на пробел с помощью -d ' ', вы получите ошибки в конце каждой строки ввода, когда он начнет читать следующую строку ввода.

К счастью, вам вообще не нужно использовать -I {}-вы уже просто добавляете эхо-слово ввода в конец командной строки shв качестве отдельного аргумента, то есть xargs' поведение по умолчанию без -I.

В сценарии оболочки вы ссылаетесь на аргумент по его позиционному параметру (, т.е. как $1), как и в любом сценарии оболочки. Вы можете использовать $1столько раз, сколько хотите в сценарии оболочки.

Вам также необходимо предоставить аргумент 0 (произвольное имя для процесса sh -строка "sh" удобна -но вы можете использовать любое имя, если хотите, чтобы его было легко найти вps)для команды sh -c '...script...'. Он должен быть первым аргументом после аргумента '...script...'и будет $0внутри сценария оболочки.

Итак,вам нужно сделать что-то вроде этого (без цикла for):

xargs -n 1 sh -c \
  './hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran \
    -1 "./samples/$1_chrX_1.fastq.gz" -2 "./samples/$1_chrX_2.fastq.gz" \
    -S "./map/$1_chrX.sam"' sh <./samples.txt

или (с циклом for):

xargs sh -c '
  for f in "$@"; do \
   ./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran \
      -1 "./samples/${f}_chrX_1.fastq.gz" -2 "./samples/${f}_chrX_2.fastq.gz" \
      -S "./map/${f}_chrX.sam"
  done' sh <./samples.txt

Версия с циклом for будет быстрее, потому что ей не нужно выполнять shнесколько раз (один раз для каждого "слова" ).

Он запускается shкак можно меньше раз, при этом пределом является максимальная длина строки команды -оболочки (около 2 МБ в современных системах ). Если samples.txtне является чрезвычайно большим (более 200 000 записей ), это означает, что он будет запущен shтолько один раз.

оболочка while -цикл чтения:

xargs не нужен для такой работы. Следующее будет работать в bash и, возможно, в других оболочках, подобных Bourne -, которые поддерживают массивы и параметр -aдля read.

while read -a words; do
  for f in "${words[@]}"; do 
   ./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran \
      -1 "./samples/${f}_chrX_1.fastq.gz" \
      -2 "./samples/${f}_chrX_2.fastq.gz" \
      -S "./map/${f}_chrX.sam"
  done
done < samples.txt

Это считывает каждое слово каждой входной строки в массив bash, затем (с помощью цикла for, перебирающего каждое слово в массиве ), запускает программу hisat2 с соответствующими аргументами.

Тем не менее, см.:Почему использование цикла оболочки для обработки текста считается плохой практикой?

awk-версия:

awk '{
  for (i=1;i<=NF;i++) {
    printf "./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran -1 \"./samples/%s_chrX_1.fastq.gz\" -2 \"./samples/%s_chrX_2.fastq.gz\" -S \"./map/%s_chrX.sam\"\n", $i, $i,$i;
  }
}'./samples.txt | sh

Обратите внимание, что это направляет вывод awk в sh для выполнения. Без этой трубы в sh вывод выглядит как:

./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran -1 "./samples/ERR199044_chrX_1.fastq.gz" -2 "./samples/ERR199044_chrX_2.fastq.gz" -S "./map/ERR199044_chrX.sam"
./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran -1 "./samples/ERR188104_chrX_1.fastq.gz" -2 "./samples/ERR188104_chrX_2.fastq.gz" -S "./map/ERR188104_chrX.sam"
./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran -1 "./samples/ERR188234_chrX_1.fastq.gz" -2 "./samples/ERR188234_chrX_2.fastq.gz" -S "./map/ERR188234_chrX.sam"
./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran -1 "./samples/ERR188245_chrX_1.fastq.gz" -2 "./samples/ERR188245_chrX_2.fastq.gz" -S "./map/ERR188245_chrX.sam"

Это также будет выполняться быстро, так как сценарий sh выполняет каждую строку по мере ее вывода сценарием awk.

В качестве альтернативы вы можете использовать sprintf, чтобы поместить командную строку в переменную, а не printfв стандартный вывод. Затем вы можете использовать функцию awksystem()для ее непосредственного выполнения, аналогично приведенному ниже примеру perl:

Perl-версия:

perl -lane '
  foreach $f (@F) {
    system(qw(./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran),
      -1, "./samples/${f}_chrX_1.fastq.gz",
      -2, "./samples/${f}_chrX_2.fastq.gz",
      "-S", "./map/${f}_chrX.sam");
  };'./samples.txt

Здесь используется функция perlsystem(), поэтому команды выполняются напрямую, без необходимости передачи в sh.

Для тестового запуска -добавьте слово echoи пробел сразу после оператора qw(кавычки -.

Кстати,было бы проще добавить код, чтобы проверить, существуют ли файлы, и/или проверить, был ли каждый запуск ./hisat2-2.1.0/hisat2успешным, или пост -обработать вывод в этой версии perl, чем в версиях оболочки или awk -, особенно если бы он был написан отдельным -шрифтом, а не одним -вкладышем. Например:

#!/usr/bin/perl -w

use strict;

while(<>) {
  foreach my $f (split) {
    my $f1 = "./samples/${f}_chrX_1.fastq.gz";
    my $f2 = "./samples/${f}_chrX_2.fastq.gz";
    my $sam = "./map/${f}_chrX.sam";

    if (!(-r $f1 && -r $f2 && -r $sam)) {
      warn "Missing or unreadable file for $f\n";
      next
    };

    my $rc = system(
        qw(echo./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran),
        -1, $f1, -2, $f2, '-S', $sam
    );

    if ($rc) {
      warn "hisat2 returned non-zero exit code for $f: $rc\n";
    };
  }
}
1
28.04.2021, 23:29

Теги

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