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

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

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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.
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.
1

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

sort -r <(printf "%s\n" $input)

4 Comments

Agreed, really clever, compact and intuitive. Thank you!
Beware, though: it also doesn't work if the value of input contains any whitespace.
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.
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.
0

This works:

input=`foo/bar/*`
output=`for l in $input ; do echo $l ; done | sort -r`

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.