Sam W
Sam W

Reputation: 599

Store all subdirectories of /Volumes in an array (BASH)

I need a script that will get all of the directories within the /Volumes directory on a Mac and store them in an array. The problem that I am running into is that it is very common for there to be a space in a directory name, and that really messes things up. Here is what I've got so far:

LOCATION="/Volumes"
COUNTER=0
cd $LOCATION
OIFS=$IFS
IFS=$'\n'

for folder in *; do
[ -d "$folder" ] || continue
(( DRIVES[$COUNTER] = ${folder} ))
(( COUNTER = COUNTER + 1 ))
done
IFS=$OIFS

Here is the error that I am getting:

./getDrives.sh: line 17: DRIVES[0] = Macintosh HD : syntax error in expression (error token is "HD ")

Upvotes: 0

Views: 1177

Answers (2)

gniourf_gniourf
gniourf_gniourf

Reputation: 46843

I guess the simplest is just:

array=( /Volumes/*/ )

Notes:

  • use this with nullglob or failglob set
  • if you also want hidden directories (but not . nor ..), set dotglob
  • if you want all the directories and subdirectories (recursively), set globstar and use

    array=( /Volumes/**/ )
    

    instead.


When I say set nullglob or failglob or dotglob or globstar I mean the shell options, that can be set with, e.g.:

shopt -s nullglob

and unset with, e.g.:

shopt -u nullglob

More about these in The Shopt Builtin section of the Bash Reference Manual.


To answer your comment: you only want the basename of the directories, not the full path? easy, just do

cd /Volumes
array=( */ )

That's all. In fact, I'm suggesting you replace 6 lines of inefficient code with just one, much more efficient, line.

More generally, if you don't want to cd into /Volumes, you can easily get rid of the leading /Volumes/ like so

array=( /Volumes/*/ )
array=( "${array[@]/#\/Volumes\//}" )

Or, even better, put the leading /Volumes/ in a variable and proceed as:

location="/Volumes/"
array=( "$location"* )
array=( "${array[@]/#"$location"/}" )

Upvotes: 4

ooga
ooga

Reputation: 15501

cd /Volumes

cnt=0
for d in *; do
  [ -d "$d" ] || continue
  drv[$cnt]="$d"
  ((++cnt))
done

for d in "${drv[@]}"; do
  echo "$d"
done

Upvotes: 0

Related Questions