I have a bash like this to easily upload a file to my server:

scp 1.txt remoteserver #upload the file to a remote server.

The $1 is for input directory and I have a lot of directories. But the txt file in all those directories are not all named "1.txt". What I can confirm is that each directory only contains one txt file.

How do I locate that file in this situation?


I tried to type FILE=../"$1"/1.txt

but when I check the file with:

if [ -f "$FILE" ]

I notice it's getting a false even when the file exist.

I figured out that:

$FILE is ../test/1.txt

"$FILE" is ../test/*.txt

So do I have to remove the pair of "?

closed as unclear what you're asking by jasonwryan, Networker, chaos, jimmij, John WH Smith Mar 4 '15 at 12:54

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 2
    FILE=../"$1"/*.txt See: mywiki.wooledge.org/glob – jasonwryan Mar 4 '15 at 0:45
  • @jasonwryan When I use echo $FILE it's working and the output is as expected. But when I use if [ ! -f "$FILE" ] it gives a false. So what should I do then? – AGamePlayer Mar 4 '15 at 2:54
  • Remove the bang: you are negating the test... – jasonwryan Mar 4 '15 at 2:59
  • sorry i mean gives true! you can try it yourself. – AGamePlayer Mar 4 '15 at 3:38
  • [ -f $FILE ]... – jasonwryan Mar 4 '15 at 4:57

You can use the wildcard * for the name that you don't know. Let's say you set


Wildcard expansion only happens outside of quotes. $FILE variable still has the asterisk in it. So,

[ -f "$FILE" ]

is equivalent to

[ -f "../test/*.txt" ]

which wants a literal asterisk in the filename, but

[ -f $FILE ]

is equivalent to

[ -f ../test/*.txt ]

which gets expanded.

It is a little bit dangerous to use $FILE to hold a pattern: if your "$1" contains a space, you cannot make it work either quoted or unquoted: quoted will keep the space, but asterisk too, but unquoted will split at the space. You could play with IFS, but in this case, an intermediate variable isn't the best idea anyway.

People will cringe at this hack, but if don't have pathological filenames, it will work. What you can do is, just force filename expansion before saving it in the variable.

FILE="$(echo ../"$1"/*.txt)"

Now, the asterisk is replaced with the actual filename, and later, you can safely use the quoted version "$FILE" to protect spaces, but the asterisk is gone.

This will fail if there is no file with that name, the asterisk will be kept literal (unless you set nullglob bash option). And if there is more than one txt file there, this won't work properly either. However, this will always work

for FILE in ../"$1"/*.txt; do whatever you want to do with `"$FILE"`; done
  • Another option is find "../$1" -name "*.txt" -exec scp {} remoteserver \;. Note that this will descend into subdirectories (if any) unless you tell it not to. – G-Man Mar 4 '15 at 18:14

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