ERemarque
ERemarque

Reputation: 507

Get list of files with `ls` using template `file{1..n}` in bash script

I can create some files in my dir using template:

touch file{1..3}

For get list of files I use command:

ls file{1..3}

Output:

file1 file2 file3

But when I have tried to use same command with variables in bash script:

#/bin/bash
a=1
b=3
ls file{$a..$b}

I got error:

ls: cannot access 'file{1..3}': No such file or directory

How I understand problem is that bash interprets file{1..3} as name of file, but not as template.
I have tried to fix it but didn't help. Any help would be appreciated.

Upvotes: 1

Views: 796

Answers (3)

B.Kocis
B.Kocis

Reputation: 2020

For a more general type solution, ditching the ls could be potentially to use find. For example in combination with regex, although this might be tricky (see How to use regex with find command?):

#!/bin/bash
a=1
b=3
find . -regex "./file[$a-$b]"

Upvotes: 0

mao
mao

Reputation: 12267

For the line

ls file{$a..$b}

you could use instead:

eval ls file{$a..$b}

Check [Bash Reference].

Upvotes: 1

KamilCuk
KamilCuk

Reputation: 140940

Because Brace Expansion happens before Variable Expansion (see order of expansions).

So bash sees:

file{$a..$b}

and first tries to do brace expansion. As $a and $b (interpreted as dollar with a character, this is before variable expansion) are not a valid brace expansion token, because they need to be a single character or a number, so nothing happens in brace expansion. After it (and some other expansions) variable expansion happens and $a and $b get expanded to 1 and 3, so the resulting argument is "file{1..3}".

For you simple use case, with no spaces and/or special characters in fielnames, I would just:

ls $(seq -f file%.0f "$a" "$b")

or

seq -f file%.0f "$a" "$b" | xargs ls

or

seq "$a" "$b" | xargs -I{} ls file{}

or

seq "$a" "$b" | sed 's/^/file/' | xargs ls

or

seq "$a" "$b" | xargs printf "file%s\n" | xargs ls

Upvotes: 2

Related Questions