find /mnt/test -name "*.txt" -print0 -printf "%f\0" |
xargs -0 -n 2 bash -c 'shift $1; ./thulac < $1 > /mnt/tokenized/$2' 2 1
Вы хотите передать полное имя пути также с нулевым разделителем, чтобы, когда придет время для xargs
, чтобы разобрать список с нулевым разделителем, он может сделать это правильно.
В противном случае произойдет то, что полное имя пути к одному файлу будет объединено с базовым именем следующего файла, явление, которое вы наблюдали в случае нескольких имен файлов!
И затем вам нужно передать 2 аргумента за раз bash alligator
, иначе он будет потреблять столько аргументов, сколько ему разрешено, но он передает вашему исполняемому файлу только первые два ./thulac
.
Лучшая альтернатива - отказаться от xargs
и выполнять всю свою работу в find
, поскольку как таковая xargs работает с двумя аргументами за раз, что устраняет любые преимущества xargs
.
В этой версии мы предоставляем полный путь к bash
и вычисляем имя файла самим bash
, а не полагаемся на find
для выполнения Это.
find /mnt/test -name "*.txt" -exec bash -c './thulac < "$1" \
> "/mnt/tokenized/${1##*/}"' {} {} \;
1. Good case when only 1 file present
-print0 -printf '%f'
/mnt/test/test.txt\0test.txt
|-----------------|--------|
arg0 = /mnt/test/test.txt
arg1 = test.txt
bash -c 'thulac < $0 > /mnt/tokenized/$1'
thulac < /mnt/test/test.txt > /mnt/tokenized/test.txt
2. Error case when > 1 file present
-print0 -printf '%f'
/mnt/test/test.txt\0test.txt/mnt/test/test33.txt\0test33.txt
|-----------------|-----------------------------|----------|
arg0 = /mnt/test/test.txt
arg1 = test.txt/mnt/test/test33.txt
arg2 = test33.txt
bash -c 'thulac < $0 > /mnt/tokenized/$1'
thulac < /mnt/test/test.txt > /mnt/tokenized/test.txt/mnt/test/test33.txt
We saw that the mixup occurred due to the absence of the delimiter '\0' in the -printf "%f"
So the correct way is:
find ... -print0 -printf "%f\0" | xargs ...
Ensuring that the list is partitioned at the right places and the
sequence of fullpath1+file1\0fullpath2+file2\0... is maintained.
Now coming to the 'xargs' part, we write:
xargs -0 -n 2 bash -c '...' 2 1
Points to observe are the following:
a) '-0' => arguments to xargs will be taken to be NULL separated.
b) -n 2 => we feed 2 args at a time to bash from the total pool
delivered to xargs by find.
c) 2 1 is just a best practice to get over different shell's behavior
regarding what construes as $0, $1, $2, ...; In your particular case since you
already know that $0 -> first arg, $1 -> 2nd arg, we could just as well have
written what you did:
find ... | xargs -0 -n 2 bash -c './thulac < $0 > /mnt/tokenized/$1'