Skip to main content
we can remove the limitation of unique file names if we sort on values.
Source Link
Stéphane Chazelas
  • 586.5k
  • 96
  • 1.1k
  • 1.7k

Sorting with gawk expression (supported by bash's loopreadarray):

Sample array of filenames containing whitespaces:

filearray=("dir1/name 0010.pdf" "dir2/name 0003.pdf" "dir3/name 0040.pdf") 

readarray -t sortedfilearr < <(printf '%s\n' "${filearray[@]}" | awk -F'/' ' BEGIN{PROCINFO["sorted_in"]="@ind_num_asc"PROCINFO["sorted_in"]="@val_num_asc"} { a[$NF]=$0a[$0]=$NF } END{ for(i in a) print a[i]i}') 

The output:

echo "${sortedfilearr[*]}" dir2/name 0003.pdf dir1/name 0010.pdf dir3/name 0040.pdf 

Accessing single item:

echo "${sortedfilearr[1]}" dir1/name 0010.pdf 

That assumes there's only one file with a given name in the array and that no file path containcontains newline characters. Note that the numerical sorting of the keysvalues in @ind_num_asc@val_num_asc only applies to the leading numerical part of the key (none in this example) with fallback to lexical comparison (based on strcmp(), not the locale's sorting order) for ties.

Sorting with gawk expression (supported by bash's loop):

Sample array of filenames containing whitespaces:

filearray=("dir1/name 0010.pdf" "dir2/name 0003.pdf" "dir3/name 0040.pdf") 

readarray -t sortedfilearr < <(printf '%s\n' "${filearray[@]}" | awk -F'/' ' BEGIN{PROCINFO["sorted_in"]="@ind_num_asc"} { a[$NF]=$0 } END{ for(i in a) print a[i]}') 

The output:

echo "${sortedfilearr[*]}" dir2/name 0003.pdf dir1/name 0010.pdf dir3/name 0040.pdf 

Accessing single item:

echo "${sortedfilearr[1]}" dir1/name 0010.pdf 

That assumes there's only one file with a given name in the array and that no file path contain newline characters. Note that the numerical sorting of the keys in @ind_num_asc only applies to the leading numerical part of the key (none in this example) with fallback to lexical comparison (based on strcmp(), not the locale's sorting order) for ties.

Sorting with gawk expression (supported by bash's readarray):

Sample array of filenames containing whitespaces:

filearray=("dir1/name 0010.pdf" "dir2/name 0003.pdf" "dir3/name 0040.pdf") 

readarray -t sortedfilearr < <(printf '%s\n' "${filearray[@]}" | awk -F'/' ' BEGIN{PROCINFO["sorted_in"]="@val_num_asc"} { a[$0]=$NF } END{ for(i in a) print i}') 

The output:

echo "${sortedfilearr[*]}" dir2/name 0003.pdf dir1/name 0010.pdf dir3/name 0040.pdf 

Accessing single item:

echo "${sortedfilearr[1]}" dir1/name 0010.pdf 

That assumes that no file path contains newline characters. Note that the numerical sorting of the values in @val_num_asc only applies to the leading numerical part of the key (none in this example) with fallback to lexical comparison (based on strcmp(), not the locale's sorting order) for ties.

simplified. Clarify that the sorting is not numerical in this example.
Source Link
Stéphane Chazelas
  • 586.5k
  • 96
  • 1.1k
  • 1.7k

Sorting with gawk expression (supported by bash's loop):

Sample array of filenames containing whitespaces:

filearray=("dir1/name 0010.pdf" "dir2/name 0003.pdf" "dir3/name 0040.pdf") 

sortedfilearr=() while readreadarray -r l; do t sortedfilearr < sortedfilearr+=<("$l")printf  done'%s\n' <"${filearray[@]}" <(| awk -F'/' 'BEGIN{PROCINFO["sorted_in"]="@ind_num_asc"}{'  a[$NF]=$0  BEGIN{PROCINFO["sorted_in"]="@ind_num_asc"}   { a[$NF]=$0 }  END{ for(i in a) print a[i]}' <(for i in "${filearray[@]}"; do echo "$i"; done)) 

The output:

echo "${sortedfilearr[*]}" dir2/name 0003.pdf dir1/name 0010.pdf dir3/name 0040.pdf 

Accessing single item:

echo "${sortedfilearr[1]}" dir1/name 0010.pdf 

That assumes there's only one file with a given name in the array and that no file path contain newline characters. Note that the numerical sorting of the keys in @ind_num_asc only applies to the leading numerical part of the key (none in this example) with fallback to lexical comparison (based on strcmp(), not the locale's sorting order) for ties.

Sorting with gawk expression (supported by bash's loop):

Sample array of filenames containing whitespaces:

filearray=("dir1/name 0010.pdf" "dir2/name 0003.pdf" "dir3/name 0040.pdf") 

sortedfilearr=() while read -r l; do  sortedfilearr+=("$l")  done < <(awk -F'/' 'BEGIN{PROCINFO["sorted_in"]="@ind_num_asc"}{ a[$NF]=$0 }   END{ for(i in a) print a[i]}' <(for i in "${filearray[@]}"; do echo "$i"; done)) 

The output:

echo "${sortedfilearr[*]}" dir2/name 0003.pdf dir1/name 0010.pdf dir3/name 0040.pdf 

Accessing single item:

echo "${sortedfilearr[1]}" dir1/name 0010.pdf 

Sorting with gawk expression (supported by bash's loop):

Sample array of filenames containing whitespaces:

filearray=("dir1/name 0010.pdf" "dir2/name 0003.pdf" "dir3/name 0040.pdf") 

readarray -t sortedfilearr < <(printf '%s\n' "${filearray[@]}" | awk -F'/' '    BEGIN{PROCINFO["sorted_in"]="@ind_num_asc"} { a[$NF]=$0 }  END{ for(i in a) print a[i]}') 

The output:

echo "${sortedfilearr[*]}" dir2/name 0003.pdf dir1/name 0010.pdf dir3/name 0040.pdf 

Accessing single item:

echo "${sortedfilearr[1]}" dir1/name 0010.pdf 

That assumes there's only one file with a given name in the array and that no file path contain newline characters. Note that the numerical sorting of the keys in @ind_num_asc only applies to the leading numerical part of the key (none in this example) with fallback to lexical comparison (based on strcmp(), not the locale's sorting order) for ties.

extended solution
Source Link
RomanPerekhrest
  • 30.9k
  • 5
  • 47
  • 68

Sorting with single gawk expression (supported by bash's for loop):

Sample array of filenames containing whitespaces:

filearray=("dir1/name 0010.pdf" "dir2/name 0003.pdf" "dir3/name 0040.pdf") 

sortedfilearr=($) while read -r l; do sortedfilearr+=("$l") done < <(awk -F'/' 'BEGIN{PROCINFO["sorted_in"]="@ind_num_asc"}{ a[$NF]=$0 }   END{ for(i in a) print a[i]}' <(for i in "${filearray[@]}"; do echo "$i"; done))) echo "${sortedfilearr[@]}" 

The output:

echo "${sortedfilearr[*]}" dir2/name 0003.pdf dir1/name 0010.pdf dir3/name 0040.pdf 

Accessing single item:

echo "${sortedfilearr[1]}" dir1/name 0010.pdf 

Sorting with single gawk expression (supported by bash's for loop):

Sample array of filenames containing whitespaces:

filearray=("dir1/name 0010.pdf" "dir2/name 0003.pdf" "dir3/name 0040.pdf") 

sortedfilearr=($(awk -F'/' 'BEGIN{PROCINFO["sorted_in"]="@ind_num_asc"}{ a[$NF]=$0 } END{ for(i in a) print a[i]}' <(for i in "${filearray[@]}"; do echo "$i"; done))) echo "${sortedfilearr[@]}" 

The output:

dir2/name 0003.pdf dir1/name 0010.pdf dir3/name 0040.pdf 

Sorting with gawk expression (supported by bash's loop):

Sample array of filenames containing whitespaces:

filearray=("dir1/name 0010.pdf" "dir2/name 0003.pdf" "dir3/name 0040.pdf") 

sortedfilearr=() while read -r l; do sortedfilearr+=("$l") done < <(awk -F'/' 'BEGIN{PROCINFO["sorted_in"]="@ind_num_asc"}{ a[$NF]=$0 }   END{ for(i in a) print a[i]}' <(for i in "${filearray[@]}"; do echo "$i"; done)) 

The output:

echo "${sortedfilearr[*]}" dir2/name 0003.pdf dir1/name 0010.pdf dir3/name 0040.pdf 

Accessing single item:

echo "${sortedfilearr[1]}" dir1/name 0010.pdf 
Source Link
RomanPerekhrest
  • 30.9k
  • 5
  • 47
  • 68
Loading