2

I'm trying to create a variable with a list of files in it so that I can iterate through them. I'm doing so like this:

FILES=(`ls *.jpg`)
FILES="${FILES[@]}"

When I run this script, it simply throws:

ls: cannot access *.jpg: No such file or directory

I've looked at some other answers for issues similar to this, and I'm fairly sure this isn't a permissions issue, as adding sudo to the front doesn't have any effect and I am root. I've also checked the permissions on the script itself and they are -rwxr-xr-x, so I think I'm good there.

Any idea how I can fix this?

Kirk Sefchik
  • 673
  • 1
  • 9
  • 22
  • 5
    This worked perfectly for me. There are some .jpg files in the directory you are running your script? – Iago Carvalho Apr 23 '19 at 22:06
  • 1
    What are you actually trying to accomplish? For most purposes the first line would be better done as `FILES=(*.jpg)` (see [here](https://mywiki.wooledge.org/ParsingLs)), and the second line mixes treating `FILES` as an array and as a plain variable in a way that doesn't make any sense (and will have bad consequences). – Gordon Davisson Apr 24 '19 at 01:32

1 Answers1

1

This Shellcheck-clean code demonstrates how to reliably populate a Bash array with a list of files:

#! /bin/bash -p

shopt -s nullglob   # Make globs that match nothing expand to nothing
shopt -s dotglob    # Make globs match files whose names start with dot

files=( *.jpg )

declare -p files
  • Shellcheck can find many problems with Bash (and other shell) code. If you put a shebang line on the code in the question and submit it to Shellcheck it identifies several problems.
  • shopt -s nullglob prevents glob patterns like *.jpg expanding to themselves when they match nothing. Such an expansion was the cause of the error message shown in the question. There were no '.jpg' files in the directory where the code was run, ls was given a literal argument of *.jpg, and it correctly complained that the file *.jpg does not exist.
  • Using shopt -s nullglob with the code in the question would not work because running it in a directory with no .jpg files would cause it to create a list of all of the files that were in the directory (except the ones whose names begin with a dot). The list would be garbled if any of the file names contained spaces or glob patterns. Files whose names started with '-' would cause ls to do unexpected things.
    It's usually unnecessary to use the output of ls in Bash programs, and it's often dangerous to use it. See why you shouldn't parse the output of ls(1) and Bash Pitfalls #1 (for f in $(ls *.mp3)).
  • shopt -s dotglob ensures that files whose names begin with a dot (e.g. '.image.jpg') will be included in the list. Don't use if you don't want that.
  • I replaced FILES with files because uppercase variable names risk clashes with environment variables or shell builtin variables. See Correct Bash and shell script variable capitalization.
  • declare -p files just prints the value of files in a clear and unambiguous way.
pjh
  • 6,388
  • 2
  • 16
  • 17
  • Note that `nullglob` can have unexpected effects; for example `ls /some/nonexistent/dir/*.jpg` would normally print a "No such file or directory" error, but with `nullglob` it'll list the contents of the current working directory instead. So I recommend turning it off with `shopt -u nullglob` after you need it. – Gordon Davisson Apr 28 '19 at 02:04