开发者

BASH: Sort array of files with crazy names

Problem:

Need to sort array before operating on them with function.

First, array is loaded with files:

unset a i
counter=1
while IFS= read -r -d $'\0' file; do
    a[i++]="$file"
done < <(find $DIR -type f -print0)

Next, each member of array is sent to function

for f in "${a[@]}"
do
   func_hash "$f"
   [ $(expr $counter % 20) -eq 0 ] && printf "="
   counter=$((counter + 1))
done

Somehow a sort needs to be thrown into the above for loop. Have looked through the SO posts on sorting arrays but somehow my crazy file names cause issues when I try to tack on a sort.

Ideas?

Thanks!

Bubnoff

UPDATE: Here's code with sort:

while IFS= read -r -d $'\0' file; do
    func_hash "$file"
    [ $(expr $counter % 20) -eq 0 ] && printf "="
    counter=$((counter + 1))
done < <(find $DIR -type f -print0 | sort -z +1 -1)

It's sorting by full path rather than file name. Any ideas on how to sort by file name given that the path is needed for the function?

UPDATE 2: Decided to compromise.

My main goal was to avoid temp files using sort. GNU sort can write back to the original file with its '-o' option so now I can:

sort -o $OUT -t',' -k 1 $OUT

Anyone have a more 'elegant' solution ( whatever that means ).

SOLVED See jw013's answer below. 开发者_开发问答Thanks man!


EDIT

while IFS= read -r -d/ && read -r -d '' file; do
    a[i++]="$file"
done < <(find "$DIR" -type f -printf '%f/%p\0' | sort -z -t/ -k1 )

Rationale:

  • I make the assumption that / is never a legal character within a file name (which seems reasonable on most *nix filesystems since it is the path separator).
  • The -printf is used to print the file name without leading directories, then then full file name with path, separated by /. The sort takes place on the first field separated by / which should be the full file name without path.
  • The read is modified to first use / as a delimiter to throw out the pathless file name.

side note

Any POSIX shell should support the modulo operator as part of its arithmetic expansion. You can replace line with the call to external command expr in the second loop with

[ $(( counter % 20 )) -eq 0 ] ...
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜