Это будет истинно, если $ PID1 запущен: if [kill -s 0 $ PID1]
У вас может быть несколько предложений if. Они будут оценивать как ложь, если PID не работает. Этот пункт (в сочетании с другими) должен управлять потоком сценария по вашему желанию.
При работе с xargs
вы всегда должны тестировать свои решения с вводом, начинающимся с «-» и содержащим двойной пробел, и «потому что xargs
печально известен тем, что имеет дело плохо с ними:
mkdir -- '-" '"'"
seq 10 > ./-\"\ \ \'/'-" '"'".txt
Вот решение, использующее GNU Parallel:
find . -name "*.txt" -print0 |parallel -0 ./thulac '<' {} '>' {/}
<и> необходимо заключить в кавычки, поскольку в противном случае они будут интерпретироваться оболочкой, которая запускает параллельно
. Мы хотим, чтобы они вместо этого интерпретироваться оболочкой, запущенной parallel
.
Проблема с вашей командой поиска.
Чтобы разделить два имени, добавьте пробел в формате printf
find /mnt/test -name "*.txt" -print0 -printf " %f\n"
^ ( note the space above)
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'
find /tmp/test -name '*.txt' \
-exec bash -c './thulac < "$(readlink -f {})" > "/mnt/tokenized/$(basename {})"' \;
Используйте поиск для поиска файлов и выполнения команд над результатами. С помощью bash -c 'command'
вы можете выполнить несколько $ ().
Используйте readlink -f {}
, чтобы создать полный путь к результату.
Используйте базовое имя {}
, чтобы удалить путь из результата.
Вы не говорите точно, чего должен достичь ваш сценарий, но если вы хотите передать каждый нечетный файл в качестве первого аргумента и каждое четное имя файла в качестве второго аргумента, вот как это сделать переносимым способом:
t=$(mktemp)
find /tmp/test -name "*.txt" -exec sh -c '
if [ -s $1 ]
then
./thulac < "$(<$1)" > "/mnt/tokenized/$2"
else
printf "%s" "$2" > "$1"
fi' sh $t {} \;
rm $t
Если вы просто хочу передать путь и имя файла каждого найденного файла, ответ проще, по-прежнему только с использованием переносимых команд и синтаксиса (POSIX), то есть не зависит от bash, GNU find и GNU xargs:
find /tmp/test -name "*.txt" -exec sh -c '
./thulac < "$1" > "/mnt/tokenized/$(basename "$1")"' sh {} \;
Обратите внимание, что { }
нужно заключать в кавычки только при использовании оболочки fish
, что очень маловероятно.