Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am simply trying to get a bash script
to return the content of a text file.

#!/bin/bash
cat $1

the problem is.. when the path to a file is not fed to this bash script... how will it even close itself.

because via regular command line... if there is no file path being fed to the cat command.. it does not hang up.

almost as if it is waiting for something..

share|improve this question
5  
cat is waiting for input from stdin which is how it's designed. If this is a concern for you, then you should be validating your inputs (which you should be doing anyways) by doing a -z test or something. –  Joel Davis Jun 20 at 17:29
    
Just noticed @Creek posted this answer below. That's what you need to do. The cat command is doing what it needs to do. –  Joel Davis Jun 20 at 17:30
5  
Tip: always do set -u at the start of each script, at least you'll have an indication that there's a problem in the script arguments instead of calling potentially destructive commands with the wrong parameters. –  Matteo Italia Jun 20 at 23:18
    
Default $1 to /dev/null if it does not exist. –  smci Jun 21 at 4:40

6 Answers 6

up vote 13 down vote accepted

Your command also has another problem, what if the filename has spaces?

#!/bin/bash
cat "$1"

Always quote unless you have a compelling reason not to. And cat "" does not hang.

share|improve this answer
4  
cat "" doesn't hang, but it does print an error message: cat: : No such file or directory (referring to the empty string). It's better to test whether $1 exists, probably by checking the value of $#. –  Keith Thompson Jun 20 at 20:10
    
The main problem I see here is that if one is running a file system which allows an empty file name this could actually work and not error. However, as a quick hack this is fine. –  Vality Jun 20 at 21:06
    
@Darkhogg: If there is such a file the test would succeed also. I assume the OP's script is in reality more complicated and this was just an example regarding cat invocation. Other answers went more to the error handling route. Someone even deleted his answer; oh well. something for everyone here. –  frostschutz Jun 20 at 21:58
    
Not cat "$@"? –  Jefromi Jun 20 at 22:55
#!/bin/bash
if [[ "$#" -ne 1 ]]; then
    echo "Usage: $0 [INPUT FILE]" 1>&2
    exit 1
fi
cat "$1"
share|improve this answer
    
Above and beyond is generally best. –  mikeserv Jun 20 at 17:30
    
@mikeserv who? where? –  Creek Jun 20 at 17:47
4  
this is the better solution in my opinion, since it exits with error –  polym Jun 20 at 17:49
1  
@Creek - you, here. –  mikeserv Jun 20 at 18:18
1  
There are lots of votes for this answer but perhaps because this is an english only web site .. people from other parts of the world are not really voting.. it is not balanced. simplicity saves the day with the chosen answer. –  user72685 Jun 20 at 18:19

cat will ignore STDIN if you supply it with a filename. Connecting STDIN to /dev/null would be a valid solution in this context.

$ cat test.sh
#!/bin/bash
cat $1 < /dev/null
$ ./test.sh test.sh
#!/bin/bash
cat $1 < /dev/null
$ ./test.sh
$

The shortcoming of this approach is that it will return 0 if no file name is supplied. No way around that. Failure to open the specified file will still return failure.

share|improve this answer

I would say that cat is an unsuitable tool here and this is why you are getting this undesired behaviour, cat is designed to concatenate a set of files and write the output to another file, it is a quirk of the implementation that the default input is stdin and the default output is stdout.

I would say a far more suitable command here would be:

#!/bin/bash
cp ${1} /dev/stdout

The dev stdout directory is originally Linux only, however before I am yelled at for using a platform specific construct bash (the shell the op explicitly stated they are using) implements /dev/stdout as a builtin so is therefore usable on any platform with bash or ksh.

cp is a utility more suitable here as it is designed to copy the contents from one file to another and that is exactly what we are doing here, copying $1 to stdout

This command will also usefully fail given no input and works on any system with bash, note it does assume that the user has properly escaped any file names with odd chars like space or \n.

share|improve this answer
3  
Honestly, this seems to me like an overcomplication; cat was born to concatenate files, but everybody uses it just to show files contents probably since the first version of UNIX, and I see nothing wrong with that - cat "filename" is way shorter, more portable and more idiomatic than cp filename /dev/stdout. –  Matteo Italia Jun 20 at 23:16
    
@MatteoItalia I give you that it is shorter, and potentially more idiomatic but it is not significantly more portable, every shell I have seen in over a decade (with the possible exception of csh) had implemented the cp version, I will note that there is a performance impact if your chosen shell makes one a builtin and the other an external command. However if neither are builtin cp will be faster. Regarding the expressiveness I suppose it depends what you are used to. –  Vality Jun 21 at 10:20
    
@Vality Why should cp be faster if both aren't builtin? –  heinrich5991 Jun 22 at 15:58
    
@heinrich5991 I have benchmarked this for a 512MB text file in a variety of machines, on average with these machines cat takes 1.79 seconds and cp takes 1.42 seconds. It seems from running a performance analyzer that cat is copying in small chunks and running a loop for every char printed, cp just splices the files together at high speed. –  Vality Jun 22 at 18:08

Default $1 to /dev/null if it does not exist.

(You can easily figure out the bash syntax for that)

share|improve this answer
: | cat $1

This would be the shortest piece of code that would work. It should ignore the absence of a file silently.

Howeverm, is this really what you need? I agree with @Vality that you probably should not use cat in this context.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.