1

I have seen way too many duplicates of this, but none of the answer codes or tips ever helped me, so I'm left confused.

input=/foo/bar/*;
#Contains something along the lines of 
#/foo/bar/file1 /foo/bar/file2 /foo/bar/file3
#And I simply need
#/foo/bar/file3 /foo/bar/file2 /foo/bar/file1

output=($(for l in ${input[@]}; do echo $l; done | sort));
#Doesn't work, returns only the last entry from input

output=$(sort -nr ${input});
#Works, returns everything correctly reversed, but outputs the file contents and not the pathnames;
output=($(sort -nr ${input}));
#Outputs only the last entry and also its contents and not the pathname;

I tried many more options, but I'm not gonna fill this whole page with them, you get the gist.

Duplicates: (None of them helpful to me)

How can I sort the string array in linux bash shell?

How to sort an array in BASH

custom sort bash array

Sorting bash arguments alphabetically

Community
  • 1
  • 1
niraami
  • 646
  • 8
  • 18
  • 1
    `$input` is not an array, it's a string. Also, how is `${a[@]}` populated? – choroba Sep 19 '16 at 21:17
  • @choroba Ops, I just copy and pasted from the other SO question because I didn't have the code anymore. – niraami Sep 19 '16 at 21:22
  • `input` contains exactly the string `/foo/bar/*`; pathname expansion does not occur in assignment statements. – chepner Sep 20 '16 at 00:59

3 Answers3

3

You're confused about what is an array in bash: this does not declare an array:

input=/foo/bar/*

$input is just the string "/foo/bar/*" -- the list of files does not get expanded until you do something like for i in ${input[@]} where the "array" expansion is unquoted.

You want this:

input=( /foo/bar/* )
mapfile -t output < <(printf "%s\n" "${input[@]}" | sort -nr)

I don't have time to explain it. I'll come back later.

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • Yeah, that's probably it. I'm pretty new to Bash, and considering nearly every list-type structure in C++, Lua, Python... (VB.NET - but I don't want to talk about that) is an array I automatically assumed the same here. – niraami Sep 19 '16 at 21:29
  • `bash` is very poor in data structures, because it wasn't designed to process data; it's a glue language to facilitate running other programs. – chepner Sep 20 '16 at 01:02
1

You can use sort -r with printf, where input containg glob string to match your filenames:

sort -r <(printf "%s\n" $input)
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 1
    Agreed, really clever, compact and intuitive. Thank you! – niraami Sep 19 '16 at 21:31
  • Beware, though: it also doesn't work if the value of `input` contains any whitespace. – chepner Sep 20 '16 at 01:00
  • Yes I know about files with spaces but as per OP has filenames as `/foo/bar/file1 /foo/bar/file2 /foo/bar/file3`. Besides I've tested this with filenames with spaces as well. I think filenames with newlines will have issues though. – anubhava Sep 20 '16 at 06:10
  • Yeah, I have no intention of using spaces in my pathnames, it's a static directory with set (by me) filenames - I just wanted for it to be a little modular. – niraami Sep 20 '16 at 11:37
0

This works:

input=`foo/bar/*`
output=`for l in $input ; do echo $l ; done | sort -r`
Juan Tomas
  • 4,905
  • 3
  • 14
  • 19