2

I'm trying to learn bash and I'm trying to list the files I have in a folder using a bash script from a.sh, like this:

1: a.sh
2: b.sh
3: c.sh

I've looked at ls and find commands, but they don't seem to prefix numerically like I want. Please Help!

1
  • ls -q | grep -n ^ should work with all kind of filenames if you don't mind seeing question marks instead of funky chars. By the way, is this homework ? Commented Feb 25, 2016 at 18:50

2 Answers 2

5

There are many ways of doing this. For example, if you are sure your file names don't contain newlines, you can do:

$ ls | cat -n
     1  a.sh
     2  b.sh
     3  c.sh
     4  d.sh

A safer way that can deal with file names containing newlines or any other strange characters:

$ c=0; for file in *; do ((c++)); printf '%s : %s\n' "$c" "$file"; done
1 : a.sh
2 : b.sh
3 : c.sh
4 : d.sh

To see why the latter two are better, create a file name that contains newlines:

$ touch 'a long file name'
$ touch 'another long filename, this one has'$'\n''a newline character!'

Now, compare the output of the two approaches:

$ ls | cat -n
     1  a long file name
     2  another long filename, this one has
     3  a newline character!
     4  a.sh
     5  b.sh
     6  c.sh
     7  d.sh

As you can see above, parsing ls (which is generally a bad idea) results in the file name with the newline being treated as two separate files. The correct output is:

$ c=0; for file in *; do ((c++)); printf '%s : %s\n' "$c" "$file"; done
1 : a long file name
2 : another long filename, this one has
a newline character!
3 : a.sh
4 : b.sh
5 : c.sh
6 : d.sh

As @Vikyboss points out in the comments, the shell solution above will set the variable $c which will persist after the loop exits. To avoid that, you could add unset c at the end, or use yet another approach. For example:

$ perl -le 'for(0..$#ARGV){print $_+1 ." : $ARGV[$_]"}' *
1 : a long file name
2 : another long filename, this one has
a newline character!
3 : a.sh
4 : b.sh
5 : c.sh
6 : d.sh
3
  • Note: Your second solution adds(pollutes?) variable c to the current shell of execution. Commented Feb 25, 2016 at 18:53
  • @Vikyboss true. You can always unset c at the end if that's a problem. Still, I added a perl solution that doesn't have this issue. Commented Feb 25, 2016 at 18:57
  • You could always do: f(){ local i; for ((i=1; i<=$#;i++)); do printf '%03d: %s\n' "$i" "${!i}"; done; }; f * and if even the function is considered pollution: unset -f . However, no variable or function will remain when the code is executed from a script. So, I do not see pollution as anything important. Commented Feb 25, 2016 at 20:30
1

This will do?

ls | awk '{print NR": "$0}'
1: andy
2: a.out
3: exclude

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.