Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

Say that in a given directory I got

tzury@x200:~/Desktop/sandbox$ ls -l
total 20
drwxr-xr-x 2 tzury tzury 4096 2011-03-09 10:19 N00.P000
drwxr-xr-x 2 tzury tzury 4096 2011-03-09 10:19 N00.P001
drwxr-xr-x 2 tzury tzury 4096 2011-03-09 10:19 N00.P002
drwxr-xr-x 2 tzury tzury 4096 2011-03-09 10:19 N00.P003
drwxr-xr-x 2 tzury tzury 4096 2011-03-09 10:19 N00.P004
drwxr-xr-x 2 tzury tzury 4096 2011-03-09 10:19 N01.P000
drwxr-xr-x 2 tzury tzury 4096 2011-03-09 10:19 N01.P001
drwxr-xr-x 2 tzury tzury 4096 2011-03-09 10:19 N01.P002

I seek for a bash way to grab the list of files which their name is either grater or smaller than a given parameter, for instance:

$ my_finder lt N00.P003

shall return N00.P000, N00.P001 and N00.P002

$ my_finder gt N00.P003

shall return N00.P004, N01.P000, N01.P001 and N01.P002

I was thinking of iterating over for name in $(ls) and while $name != $2 but believe there are more elegant way of doing so

share|improve this question
add comment

3 Answers

up vote 3 down vote accepted

Never ever iterate over ls output!

Here's my suggestion:

for fn in *; do test "$fn" -$1 "$2" && echo "$fn"; done

Edit:

Sorry. The above works only if $fn and $2 are numeric. You'll have to replace -$1 with $op, and prepend a selector in front of the loop. op="<" or op=">" depending on $1 is lt or gt, respectively.

share|improve this answer
    
many thanks. in regards ot the advise of "never ever iterate over ls (or find)" I would love if you can elaborate about this ab it more, and what if in a case where I iterate over a directory which is content is totally under my control, is this advise still applies? –  Tzury Bar Yochay Mar 9 '11 at 10:34
1  
The problem with ls is that it will happily list files whose names contain space or other whitespace, and thus such files' names will be treated as separate words. Unless you take care to actually wrap each file. Now, word splitting happens before globbing. So, the '*' will not experience word splitting when it is fed to the for loop. –  pepoluan Mar 9 '11 at 10:54
add comment
for num in {001..003} ;do ls N00.P"$num"; done

Replace 003 with limit you want to put.

share|improve this answer
    
it is missing from my example though, it can happen that parameter might be N01.P001 which means in that case, N00.P"$num" pattern won't work –  Tzury Bar Yochay Mar 9 '11 at 9:22
add comment

Unfortunately for this technique, /usr/bin/test doesn't support STRING > STRING, however the shell builtin test does so we have to invoke the shell in order to be able to use find -exec and avoid a loop:

find $PWD -type f -exec sh -c 'test "{}" "<" "$PWD/N00.P004"' \; -print

The question remains whether spawning a shell repeatedly is more efficient than running a loop. However, the chief advantage to using this technique is that you can do recursive processing without a pipe.

You can create a function that uses this technique and allows you to use gt and lt instead of having to pass quoted < or >:

my_finder () { 
    local op=$1
    case "$op" in
        "gt") op='>';;
        "lt") op='<';;
           *) echo "Invalid operator"; return 1;;
    esac
    find $PWD -type f -exec sh -c 'test "{}" "$op" "$PWD/$2"' \; -print
}

Usage:

$ my_finder gt N00.P003
/home/tzury/Desktop/sandbox/N00.P004
/home/tzury/Desktop/sandbox/N01.P000
/home/tzury/Desktop/sandbox/N01.P001
/home/tzury/Desktop/sandbox/N01.P002
share|improve this answer
    
what do you mean does not support S1 > S2? @pepoluan's answer works for me in both cases, gt and lt –  Tzury Bar Yochay Mar 10 '11 at 3:44
    
@TzuryBarYochay: That answer is using the shell builtin test, I was referring to /usr/bin/test as the first sentence in my answer says. They're not the same thing, though they're very similar. What I failed to mention in my answer is that, if /usr/bin/test did support < and > then my find command could be written: find $PWD -type f -exec test "{}" "<" "$PWD/N00.P004" \; -print. I will add a clarification. –  Dennis Williamson Mar 10 '11 at 3:54
add comment

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.