0

Everybody says it is bad, bad, very bad to use ls to parse. This is a script that will pick out a log file. I don't want to glob the whole directory, $1 is the name of the file I want to look at, and of those files, I only want to see the last two. How do I do this without using ls ?

for i in $(ls -ltr ~/logs/autosys/*${1}* | tail -2) ; do
    if [[ ${i} =~ ".out" ]] ; then
    tailpath=$(echo ${i%.*} | awk '{print $9}')
    fi
done
6
  • I don't understand what this code is supposed to do. Commented Aug 7, 2018 at 21:17
  • 1
    I think it's "take the two newest files in ~/logs/autosys with names containing $1, then do something with them". Commented Aug 7, 2018 at 21:18
  • 2
    If you want to compare by last modification time and can't use the filename: BashFAQ/003 Commented Aug 7, 2018 at 21:19
  • @Benjamin - you are correct - that is what the snippet does - it is part of something larger Commented Aug 7, 2018 at 21:26
  • ls -t | head -n2 will give you just the filename, you don't need to parse the ls output. Commented Aug 7, 2018 at 21:59

2 Answers 2

1

I suspect you want

logfile=$(stat -c "%Y:%n" ~/logs/autosys/*"$1"*.out | sort -t: -k1,1n | tail -1 | cut -d: -f2-)
Sign up to request clarification or add additional context in comments.

4 Comments

Shouldn't it be tail -2 (the two latest ones, as per question)?
The logic of that loop is odd. The variable is set each tie through, so only the last iteration counts
I think it's incorrect in the code in the question, just pointing out that the text says "last two".
It appears that the OP wants the ".out" file that is in the last two. I'm short-circuiting that
1

Without using ls, you would iterate over the files unconditionally, calling stat on each one, and keeping track of the two newest files yourself.

t0=0
t1=0

for i in ~/logs/autosys/*"${1}"*; do
    # Assuming GNU stat; syntax for other implementations may vary
    t=$(stat -c "%Y" "$i")
    if (( t > t0 )); then
        f1=$f0
        f0=$i
        t1=$t0
        t0=$t
    elif (( t > t1 )); then
        t1=$t
        f1=$i
    fi
done

Now $f0 and $f1 contain the names of the two newest files.

The fact is, bash isn't really suited for doing this task easily and efficiently. (The bash distribution does contain a built-in stat command, but it doesn't seem to be commonly installed.)

zsh, on the other hand, makes this task rather easy:

% files=(~/logs/autosys/*${1}*(Om[-2,-1]))

The glob qualifiers Om and [-2,-1] sort by modification date and limit the match to the last two elements, respectively. ((om[1,2]) also works.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.