Richi D
Richi D

Reputation: 41

Array of all files in a directory, except one

Trying to figure out how to include all .txt files except one called manifest.txt.

FILES=(path/to/*.txt) 

Upvotes: 4

Views: 1410

Answers (4)

Benjamin W.
Benjamin W.

Reputation: 52251

You can use extended glob patterns for this:

shopt -s extglob
files=(path/to/!(manifest).txt)

The !(pattern-list) pattern matches "anything except one of the given patterns".

Note that this exactly excludes manifest.txt and nothing else; mmanifest.txt, for example, would still go in to the array.


As a side note: a glob that matches nothing at all expands to itself (see the manual and this question). This behaviour can be changed using the nullglob (expand to empty string) and failglob (print error message) shell options.

Upvotes: 5

dawg
dawg

Reputation: 103998

I think this is best handled with an associative array even if just one element.

Consider:

$ touch f{1..6}.txt manifest.txt
$ ls *.txt
f1.txt      f3.txt      f5.txt      manifest.txt
f2.txt      f4.txt      f6.txt

You can create an associative array for the names you wish to exclude:

declare -A exclude 
for f in f1.txt f5.txt manifest.txt; do 
    exclude[$f]=1
done

Then add files to an array that are not in the associative array:

files=()
for fn in *.txt; do
    [[ ${exclude[$fn]} ]] && continue
    files+=("$fn")  
done

$ echo "${files[@]}"
f2.txt f3.txt f4.txt f6.txt

This approach allows any number of exclusions from the list of files.

Upvotes: 1

Fred
Fred

Reputation: 6995

You can build the array one file at a time, avoiding the file you do not want :

declare -a files=()
for file in /path/to/files/*
do
  ! [[ -e "$file" ]] || [[ "$file" = */manifest.txt ]] || files+=("$file")
done

Please note that globbing in the for statement does not cause problems with whitespace (even newlines) in filenames.

EDIT

I added a test for file existence to handle the case where the glob fails and the nullglob option is not set.

Upvotes: 2

Grzegorz Górkiewicz
Grzegorz Górkiewicz

Reputation: 4596

FILES=($(ls /path/to/*.txt | grep -wv '^manifest.txt$'))

Upvotes: 1

Related Questions