7

I have a directory that contains the following files:

file1a file1ab file12A2 file1Ab file1ab

I want to list all files that start with file1 and followed by two letter at most!

The solution I have proposed is as follows:

ls | grep -i file1 [az] {2}

But it does not work!

I want to know why? and how to list?

0

3 Answers 3

11

You don't need piping, grep or ls. Just use shell globbing.

In bash, using extglob pattern (should be enabled by default in interactive sessions, if not do shopt -s extglob to set it first):

file1@(|?|??)

? matched any single character, @(||) selects any of the patterns separated by |.

If you only meant to match any characters between a-z and A-Z, use use character class [:alpha:] which denotes all alphabetic characters in the current locale:

file1@(|[[:alpha:]]|[[:alpha:]][[:alpha:]])

Example:

$ ls -1
file1
file112
file11a
file12A2
file1a
file1ab
file1Ab
file1as
file2
fileadb

$ ls -1 file1@(|[[:alpha:]]|[[:alpha:]][[:alpha:]]))
file1
file1a
file1ab
file1Ab
file1as

zsh supports this natively:

file1(|[[:alpha:]]|[[:alpha:]][[:alpha:]])

I am answering this portion very reluctantly, upon request from OP.

Any future reader, Don't parse ls, use globbing.

Using ls and grep:

ls | grep -E '^file1[[:alpha:]]{,2}$'

Example:

% ls | grep -E '^file1[[:alpha:]]{,2}$'
file1
file1a
file1ab
file1Ab
file1as
13
  • Thank you ! but the problem is that we have not yet studied all that! is it possible to do this task using ls and grep and piping ?
    – Tifizza
    Nov 19, 2015 at 11:55
  • 1
    @MahmoudAssyass Check my edits but you absolutely should (read must) use shell globbing..
    – heemayl
    Nov 19, 2015 at 12:04
  • I'm very sorry to disturb you! I am aware that stupid questions annoy you! Thank you for bearing with me
    – Tifizza
    Nov 19, 2015 at 12:12
  • 1
    @MahmoudAssyass Come on..nobody is disturbing anybody..i am very happy to help you..just a caveat that you should start using globbing for these kind of tasks rather than ugly ls | grep .. :)
    – heemayl
    Nov 19, 2015 at 12:14
  • Thank you so much for your help and also for your quick response. It is definitely appreciated.
    – Tifizza
    Nov 19, 2015 at 12:19
3

Whats about find?

find . -maxdepth 1 -regextype posix-egrep -iregex '\./file1[a-z]{,2}.*'
2
  • I know very well that we can solve this problem thanks to other methods, but is it possible to do that just by using grep and ls and piping !
    – Tifizza
    Nov 19, 2015 at 12:01
  • 1
    I don't understand why you are focused on grep and ls, except as an exercise. Find is the preferred way to do such complicated tasks, as it can be done in a single command and not require a shell master. Furthermore, it can be MUCH more efficient on large directories, as it need not output non-matching strings. A minor efficiency to be sure, but an efficiency nevertheless. Although, I must admit that the line above does look quite intimidating: find is not known for ease of use :-) Nov 19, 2015 at 20:07
3

find with -regex flag is more appropriate for this sort of job, especially since it's a general rule that output of ls should never be parsed.

However, you've stated that you are looking for files only in one directory ( not descending into subdirectories ), and that you'd specifically want ls and grep. The solution is

\ls | grep -E 'file1[a-z]{2,}' 

Considering also that you are searching in the current directory, but avoiding parsing ls, here's another solution

 for file in * ; do echo "$file" | grep -E 'file1[a-z]{2,}' ;done                                        
./file1ab
./file1abc

In my current directory, I have two files, file1ab and file1abc. In both cases, the result is the following:

xieerqi:$ for file in * ; do echo "$file" | grep -E 'file1[a-z]{2,}' ;done                                        
./file1ab
./file1abc

xieerqi:$ \ls | grep -E 'file1[a-z]{2,}'                                                                            
file1ab
file1abc

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .