Read into bash script and pass script argument
I have a question. Unfortunately I couldn't find an answer. How do I pass arguments to a script that are the result of another command. For example:
ls | ./myscript.sh
I want to pipe the result ls
to myscript
. And if I ran the above command and the script:
#!/bin/bash
read some
for arg in $@
do
grep $some $arg
done
then he didn't wait to read the some variable , and the some variable gets its value from the result obtained from the command ls
? How it works? I want the following: To specify the script file names (using the ls command), after that the user has to enter some line, and I want to print every line containing the entered word. I didn't know why the code above doesn't work. Thanks in advance.
source to share
xargs
is a utility used to convert stdin input to command line arguments.
Naively, you can do the following:
ls | xargs ./myscript.sh
However, this will not work as expected with filenames that have inline spaces as they will be split across multiple arguments.
Please note that ./myscript.sh $(ls)
has the same problem.
If your implementation xargs
supports a non-standard option -0
for parsing a NUL-sectioned input, you can fix it like this:
printf '%s\0' * | xargs -0 ./myscript.sh
Otherwise, use the following, which, however, will only work if the filenames were not embedded in characters "
(or embedded newlines):
printf '"%s" ' * | xargs ./myscript.sh
Since your stdin input comes from filenames in this case, you can use find
that essentially has functionality built in xargs
:
find . -type f -maxdepth 1 -exec ./myscript.sh {} +
- Note that
find . -type f -maxdepth 1
it essentially does the same thing,ls
but there are subtle differences, in particular that each matching filename will be prefixed with./
and that filenames may not be sorted. -
-exec ./myscript.sh {} +
calls your script with as many filenames ({}
) as it can fit on one command line (+
) - just likexargs
- it usually does all of them.
Note that both xargs
and find ... -exec ... +
may result in multiple calls to the specified command if not all arguments match the same command line.
However, given how long command lines have been allowed on modern platforms, this rarely happens - it only happens if you have a huge number of files in your directory and / or their names are very long.
source to share
You can run the command like this:
./myscript.sh $(ls)
This will prompt the user for the variable some
and grep through the results ls
for files containing the value entered by the user.
However, you are likely to run into problems with this approach, as spaces and other characters can cause your for loop to receive invalid input.
With this in mind, you can also watch find
and xargs
to achieve something like this , depending on how complex your script is. For example:
find . -type f -print0 |xargs -0 grep "test"
source to share