2

So, I need to write a shell script that accepts a file path as an argument and uses it within the shell script. I know that I could do something like:

$ ./script filename

With this solution, this would make it so that I could access this filename string using $1 in the shell script.

However, I'm wondering if it is possible to use input redirection instead so I could pass the filename using it:

$ ./script < filename

If so, how would I access this filename in the shell script?
I'm fairly new to shell script coding so I'm not sure if this is even possible.

3 Answers 3

5

You can extract the name of file passed with < by listing /proc/<pid>/fd directory, as follows:

ls -ltr /proc/$$/fd

Then

$ cat myscript.sh
ls -ltr /proc/$$/fd
$ ./myscript.sh < hello
total 0
lr-x------ 1 u g 64 Feb 25 08:42 255 -> /tmp/myscript.sh
lrwx------ 1 u g 64 Feb 25 08:42 2 -> /dev/pts/0
lrwx------ 1 u g 64 Feb 25 08:42 1 -> /dev/pts/0
lr-x------ 1 u g 64 Feb 25 08:42 0 -> /tmp/hello

I can't guess whether this is useful

And doesn't work when input is passed through a pipe

$ cat hello| ./myscript.sh 
total 0
lr-x------ 1 u p 64 Feb 25 08:50 255 -> /tmp/myscript.sh
lrwx------ 1 u p 64 Feb 25 08:50 2 -> /dev/pts/0
lrwx------ 1 u p 64 Feb 25 08:50 1 -> /dev/pts/0
lr-x------ 1 u p 64 Feb 25 08:50 0 -> pipe:[82796]

Alternatively, you can use lsof and a little line handling to extract value

 filename=$(/usr/sbin/lsof -p $$| grep " 0u"| cut -c 60-)
Sign up to request clarification or add additional context in comments.

4 Comments

nice one, hadn't thought of that... not sure if that's portable, but neat trick all the same... come to think of it, the same could be achieve parsing the output of lsof -p $$.
@isedev Thank you, lsof -p $$ seems more portable. It's possible too to use lsof to follow pipes, but it seems as useless as the basic case
Is it possible to translate /proc/$$/fd/0 to the actual file name passed?
filename=/usr/sbin/lsof -p $$| grep " 0u" cut -c 60- works for me
2

You cannot access the filename in the case of ./script < filename but only its contents. The reason is that the shell opens filename and set the corresponding file descriptor to be the standard input of the ./script.

Comments

1

With your second solution you don't access the filename, but your script's standard input is coming from the file.

With the first solution printing the file would look like this:

cat "$1"

With the second:

while read line; do echo "$line"; done

1 Comment

should be while IFS= read -r line;, and you're also missing quotes around $line (echo "$line") .

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.