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.

+3


source to share


2 answers


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 like xargs

    - 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.

+4


source


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"

+1


source







All Articles