1

I have the following find command with the following output:

$ find -name '*.jpg'
./public_html/github/screencasts-gh-pages/reactiveDataVis/presentation/images/telescope.jpg
./public_html/github/screencasts-gh-pages/introToBackbone/presentation/images/telescope.jpg
./public_html/github/StarCraft-master/img/Maps/(6)Thin Ice.jpg
./public_html/github/StarCraft-master/img/Maps/Snapshot.jpg
./public_html/github/StarCraft-master/img/Maps/Map_Grass.jpg
./public_html/github/StarCraft-master/img/Maps/(8)TheHunters.jpg
./public_html/github/StarCraft-master/img/Maps/(2)Volcanis.jpg
./public_html/github/StarCraft-master/img/Maps/(3)Trench wars.jpg
./public_html/github/StarCraft-master/img/Maps/(8)BigGameHunters.jpg
./public_html/github/StarCraft-master/img/Maps/(8)Turbo.jpg
./public_html/github/StarCraft-master/img/Maps/(4)Blood Bath.jpg
./public_html/github/StarCraft-master/img/Maps/(2)Switchback.jpg
./public_html/github/StarCraft-master/img/Maps/Original/(6)Thin Ice.jpg
./public_html/github/StarCraft-master/img/Maps/Original/Map_Grass.jpg
./public_html/github/StarCraft-master/img/Maps/Original/(8)TheHunters.jpg
./public_html/github/StarCraft-master/img/Maps/Original/(2)Volcanis.jpg
./public_html/github/StarCraft-master/img/Maps/Original/(3)Trench wars.jpg
./public_html/github/StarCraft-master/img/Maps/Original/(8)BigGameHunters.jpg
./public_html/github/StarCraft-master/img/Maps/Original/(8)Turbo.jpg
./public_html/github/StarCraft-master/img/Maps/Original/(4)Blood Bath.jpg
./public_html/github/StarCraft-master/img/Maps/Original/(2)Switchback.jpg
./public_html/github/StarCraft-master/img/Maps/Original/(4)Orbital Relay.jpg
./public_html/github/StarCraft-master/img/Maps/(4)Orbital Relay.jpg
./public_html/github/StarCraft-master/img/Bg/GameLose.jpg
./public_html/github/StarCraft-master/img/Bg/GameWin.jpg
./public_html/github/StarCraft-master/img/Bg/GameStart.jpg
./public_html/github/StarCraft-master/img/Bg/GamePlay.jpg
./public_html/github/StarCraft-master/img/Demo/Demo.jpg
./public_html/github/flot/examples/image/hs-2004-27-a-large-web.jpg
./public_html/github/minicourse-ajax-project/other/GameLose.jpg

How do I store this output in an array? I want it to handle filenames with spaces

I have tried this arrayname=($(find -name '*.jpg')) but this just stores the first element. @ I am doing the following which seems to be just the first element?

$ arrayname=($(find -name '*.jpg'))
$ echo "$arrayname"
./public_html/github/screencasts-gh-pages/reactiveDataVis/presentation/images/telescope.jpg
$ 

I have tried here but again this just stores the 1st element

Other similar Qs
How do I capture the output from the ls or find command to store all file names in an array?
How do i store the output of a bash command in a variable?

Community
  • 1
  • 1
HattrickNZ
  • 4,373
  • 15
  • 54
  • 98
  • Works for me. Why do you think you are getting just the 1st element? What code are using to verify it? (Then again, it has a problem where it will split lines that contain space.) – Amadan Jan 25 '16 at 01:39
  • I am doing an echo on that array and it is just showing the 1st element, can you correct my ways, see my edited Q – HattrickNZ Jan 25 '16 at 01:51
  • If you are doing `echo $arrayname`, that shows the first element. If you are doing `echo "${arrayname[@]}"`, it shows the whole array. – Amadan Jan 25 '16 at 01:52
  • can i print it in this format ['a','b','c'...]? – HattrickNZ Jan 25 '16 at 01:58
  • With work, yes. Automatically, no. Use Ruby or another nice scripting language if you want convenience. – Amadan Jan 25 '16 at 01:59
  • don't have ruby, will just use np++ for now. – HattrickNZ Jan 25 '16 at 02:05
  • `printf '["' && sh -c 'IFS=",";printf "$*"' '' "${arrrayname[@]}" && echo '"]'` might work. You will not get proper escaping though. `ruby -rjson -e 'puts JSON.dump(ARGV)' "${arrayname[@]}"` should work well if you have Ruby; similar things with other nice languages. – Amadan Jan 25 '16 at 02:10
  • close that gives ["a,b,c,...,z"]. note there is also 3 r's in arrrayname – HattrickNZ Jan 25 '16 at 02:18
  • Eh yeah, ignore the first one, that's a brain fart. Needs a loop and everything, and you'd still have a problem with stuff containing quotes or backslashes. Lots of work to make bash into something it's not. – Amadan Jan 25 '16 at 02:22
  • @amadan: Try `declare -p arrayname` – rici Jan 25 '16 at 03:34

2 Answers2

3

If you know with certainty that your filenames will not contain newlines, then

mapfile -t arrayname < <(find ...)

If you want to be able to handle any file

arrayname=()
while IFS= read -d '' -r filename; do
    arrayname+=("$filename")
done < <(find ... -print0)

echo "$arrayname" will only show the first element of the array. It is equivalent to echo "${arrayname[0]}". To dump an array:

printf "%s\n" "${arrayname[@]}"
# ............^^^^^^^^^^^^^^^^^ must use exactly this form, with the quotes.

arrayname=($(find ...)) is still wrong. It will store the file ./file with spaces.txt as 3 separate elements in the array.

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • tried that `$ arrayname=() $ while IFS= read -d '' -r filename; do > arrayname+=("$filename") > done < <(find '*.jpg' -print0) find: `*.jpg': No such file or directory $` and got this error `find: `*.jpg': No such file or directory` – HattrickNZ Jan 25 '16 at 01:54
  • @glennjackman That's a great answer. May I also add this one `while read -rd '';do arr[i++]=$REPLY;done < <(find . -name '*.jpg' -print0)` , executable in Bash. – Rany Albeg Wein Jan 25 '16 at 03:39
1

If you have a sufficiently recent version of bash, you can save yourself a lot of trouble by just using a ** glob.

shopt -s globstar
files=(**/*.jpg)

The first line enables the feature. Once enabled, ** in a glob pattern will match any number (including 0) of directories in the path.

Using the glob in the array definition makes sure that whitespace is handled correctly.

To view an array in a form which could be used to define the array, use the -p (print) option to the declare builtin:

declare -p files
rici
  • 234,347
  • 28
  • 237
  • 341