Mithril Mithril -4 years ago 103
Bash Question

Find fullpath and filename then pass to a execable file as arguments

I'd like to find fullpath and filename of all

.txt
under a directory, and pass to a execable file
./thulac
.

It cost me some time to reach

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


But this only find 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 -l bash -c './thulac < $0 > $1'


Though here,
xargs
can not split
-print0 -printf "%f"
as two argument, which stuck me.

Error:

/mnt/test/1.txt: $1: ambiguous redirect


How to work it out?

Answer Source

The problem is you are not de-limiting the output of -print0 from find. It appends a \0 at end of each file name returned, which has to be read with the same delimiter, which -0 option in GNU xargs does.

See what -print0 options means from the man find page,

-print0

print the full file name on the standard output, followed by a null character (instead of the newline character that -print uses). This allows file names that contain newlines or other types of white space to be correctly interpreted by pro‐ grams that process the find output. This option corresponds to the -0 option of xargs.

So, do -0 to de-limit the output from find with a proper process-substitution syntax as

 #!/bin/bash

 while IFS= read -r -d '' file; do
     echo "$file" 
     # '$file' will have the file-name, use it however way you want 
     # to use it
 done< <(find /mnt/test -name "*.txt" -print0)
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download