0

I have this simple code

#!/bin/bash

TIMEOUT=60

# call a function that creates a file
LOG_FILE_NAME="/dir/something.txt"
create_a_file(LOG_FILE_NAME)

until [ ! -f ${LOG_FILE_NAME} ] || [ "$TIMEOUT" == "0" ]
do
    echo "Slept 1 second while waiting for file creation"
    sleep 1
    ((TIMEOUT--))
done

for file in $(ls -tr /dir/*.txt); do
    #something
done

Most times this works but sometimes I get: ls: cannot access /dir/*.txt: No such file or directory

Kam
  • 5,878
  • 10
  • 53
  • 97
  • 2
    Also see [How to iterate over files in a directory with Bash?](https://stackoverflow.com/q/20796200/608639), [Loop through all the files with a specific extension](https://stackoverflow.com/q/14505047/608639), [Iterating over each line of ls -l output](https://stackoverflow.com/q/2859908/608639) and friends. An [answer in the first question](https://stackoverflow.com/a/43606356/608639) addresses when the glob does not match. – jww Jul 17 '19 at 01:02
  • `[ ! -f ${LOG_FILE_NAME} ]` use `-e` and not `-f` as there may be a symbolic link or anything that make it not a regular file and fail the `-f` flag test. add quotes around the variable to prevent globbing so write it `[ ! -e "${LOG_FILE_NAME}" ]` instead. `[ "$TIMEOUT" == "0" ]` is testing `TIMEOUT` as a string. If you want an arithmetic test you either write `[ "$TIMEOUT" -eq 0 ]` or benefit from Bash arithmetic expression with `(( 0=--TIMEOUT ))` and you can then remove `((TIMEOUT--))` at the end of the loop. – Léa Gris Jul 17 '19 at 01:20
  • 1
    Note that `ls` is not part of bash itself, and is not recommended for use in scripts -- as jww's links describe. (See [ParsingLs](http://mywiki.wooledge.org/ParsingLs) as a focused explanation on the topic). – Charles Duffy Jul 17 '19 at 01:22
  • @Kam : This can NEVER work under bash, because the statement `create_a_file(LOG_FILE_NAME)` is syntactically invalid and the script will abort with _bash: syntax error near unexpected token `LOG_FILE_NAME'_ . – user1934428 Jul 17 '19 at 07:12

1 Answers1

0

ls: cannot access /dir/*.txt: No such file or directory

It means there are no *.txt files in /dir/. (When the glob doesn't match anything the shell passes the literal asterisk to ls, as if you had written ls '/dir/*.txt'.)

The problem is the loop condition. It shouldn't have !.

until [ -f ${LOG_FILE_NAME} ] || [ "$TIMEOUT" == "0" ]

(If the timeout hits 0 you'll still see the same error, though.)

It's better to use [[, by the way, to avoid quoting issues.

until [[ -f $LOG_FILE_NAME || $TIMEOUT == 0 ]]
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • Ahh. Until you suggested the cutover to `[[`, I was going to recommend switching to `=`, but using explicitly extended-shells-only syntax makes that moot. :) – Charles Duffy Jul 17 '19 at 01:16