As a vehicle to understand how to manipulate binding precedence with pipes, I'm trying to print the path of one file per directory - for every directory:
find $PWD -type d | xargs --delimiter "\n" -I% -n 1 (find % -maxdepth 1 | head -1)I get no matches found: (find % -maxdepth 1 | head -1). Without the brackets I would get xargs: find: terminated by signal 13 so I'm pretty sure we need to somehow make the pipes right-associative.
How do I pass xargs input to a command that contains pipes? (please don't tell me to use -exec, I want to learn how to manipulate binding precedence for other problems).
4 Answers
Here you are with xargs:
find . -type d|xargs -I % sh -c 'find % -type f -maxdepth 1 | head -1'But remember: internal loop is much faster!
time find $PWD -type d | while read dir;do find $dir -type f -maxdepth 1 | head -1;done >/dev/null 0m09.62s real 0m01.67s user 0m02.36s system
time find . -type d|xargs -I % sh -c 'find % -type f -maxdepth 1 | head -1' >/dev/null 0m12.85s real 0m01.84s user 0m02.86s system 3 Personally I don't like xargs
find $PWD -type d | while read dir;do find $dir -type f -maxdepth 1 | head -1;done 3 And this is the fastest solution with everything is internal:
time find . -type d | while read dir;do for file in "$dir"/*;do if [ -f "$file" ]; then realpath $file;break;fi;done;done >/dev/null 0m00.21s real 0m00.08s user 0m00.10s systemUnbeatable speed in shell. (I said I don't like xargs)
I know this is an old post, but here's how you could use a subshell using bash -c
find $PWD -type d | xargs --delimiter "\n" -I% -n 1 bash -c 'find % -maxdepth 1 | head -1'Let me explain : bash -c generates a subshell taking a string argument being in this case the find command. Being a subshell, you can use any command you like, as long as you keep in mind that the command is within a string and that the subshell may have a different environment than the parent shell.
1