Shell – Find fullpath and filename under a directory then pass to an executable file as arguments

command linefindlinuxshellxargs

I'd like to find fullpath and filename of all .txt under a directory, and pass to a executable file ./thulac .

It cost me some time to reach:

find /mnt/test -name "*.txt" -print0 |xargs -l bash -c './thulac < $0' 

But this only finds fullpath.

From xargs with multiple arguments

, I see:

echo argument1 argument2 argument3 | \
   xargs -l bash -c 'echo this is first:$0 second:$1 third:$2' | xargs

What I want to achieve is something like:

find /mnt/test -name "*.txt" -print0 -printf "%f" | \
   xargs -0 bash -c './thulac < $0 > $1' 

Though here, xargs can not correctly split -print0 -printf "%f" as two arguments when there are multiple files, which stuck me.


Example:

find /mnt/test -name "*.txt" -print0 -printf "%f" | \
   xargs -0 -I bash -c './thulac < $0 > /mnt/tokenized/$1'
  1. If /mnt/test only has one file the above command does work.

  2. But if /mnt/test has more than one file (no matter what the language):

    [root@localhost THULAC]# ls /mnt/test
    test33.txt  test.txt
    [root@localhost THULAC]# find /mnt/test -name "*.txt" -print0 -printf "%f" | \
        xargs -0 bash -c './thulac < $0 > /mnt/tokenized/$1'
    /mnt/test/test.txt: /mnt/tokenized/test.txt/mnt/test/test33.txt: No such file or directory
    

    As you see, xargs mixes two paths together /mnt/tokenized/test.txt/mnt/test/test33.txt , which leads to the error No such file or directory.

How to make it work?

Best Answer

find /tmp/test -name '*.txt' \
 -exec bash -c './thulac < "$(readlink -f {})" > "/mnt/tokenized/$(basename {})"' \;

Use find to search for files and to execute commands on the results. With bash -c 'command' you are able to execute multiple $().

Use readlink -f {} to create the full path to the result.

Use basename {} to strip the path from the result.

Related Question