Как отсортировать ассоциативный массив и сохранить ключи?

То, что Вы просите, не имеет большого смысла в общем случае, таким образом, это не удивительно это find не имеет никакого условия для него.

Символьная ссылка с относительной целью относительно пути символьной ссылки. Так, например, если путем пересечения каталога следующими символьными ссылками, find обнаружение a/b/c/d и a, a/b, a/b/c все относительные или абсолютные символьные ссылки (или символьные ссылки на пути с компонентами символьной ссылки), что это должно сделать?

Если Вы ищете a find предикат или GNU -printf % директива, которая расширяется до пути без символьных ссылок к файлу относительно текущего каталога или любого каталога, я боюсь, что нет ни одного.

Если Вы находитесь на Linux, можно получить полный путь тех файлов с:

find -L foo -type f -exec readlink -f {} \;

Как Вы узнали, там существует по крайней мере один realpath команда, которая принимает больше чем один параметр пути который в сочетании со стандартом -exec cmd {} + синтаксис будет намного более эффективным, так как он выполняет так же мало команд realpath по мере необходимости:

find -L foo -type f -exec realpath {} +

find -L foo -type f -print0 | xargs -r0 realpath

могло бы быть более быстрым как будто больше чем один realpath команда необходима, find может продолжить искать больше файлов в то время как первое realpath начинает работать, который даже в единственной системе процессора мог бы сделать это более эффективным.

-print0 и xargs -r0 не являются стандартными, произойдите из GNU, но найдены во многих других реализациях как самый современный BSDs.

Zsh имеет встроенную поддержку его:

print -rl foo/***/*(-.:A)

Если Вы не заботитесь о порядке сортировки, можно отключить сортировку и сделать ее немного более эффективной с:

print -rl foo/***/*(-.oN:A)

Если Вы хотите преобразовать тех, которые к относительным путям к текущему каталогу, Вы могли бы взглянуть на это ТАК вопрос.

Если Вы знаете, что все те файлы имеют абсолютный канонический путь (чей ни один из компонентов не символьные ссылки) в текущем каталоге, можно упростить его до (все еще с zsh):

files=(foo/***/*(-.:A))
print -rl -- ${files#$PWD/}

Хотя короткий и удобный, и работы независимо от того, что символьные имена файлов содержат, я сомневаюсь, что это было бы быстрее, чем find + realpath.

С Debian realpath и инструменты GNU, можно сделать:

cd -P .
find -L foo -type f -exec realpath -z {} + | 
  gawk -v p="$PWD" -v l="${#PWD}" -v RS='\0' -vORS='\0' '
    substr($0, 1, l+1) == p "/" {$0 = substr($0, l+2)}; 1' |
  xargs -r0 whatever you want to do with them

Как я понимаю теперь, существует теперь a realpath в последних версиях GNU coreutils, который имеет точную функцию, которую Вы ищете, таким образом, это - просто вопрос

find -L foo -type f -print0 |
  xargs -r0 realpath -z --relative-base . |
  xargs -r0 whatever you want to do with them

(используйте --relative-to . вместо --relative-base . если Вы хотите относительные пути даже для файлов, символьная ссылка которых свободный путь не находится ниже текущего рабочего каталога).

5
01.03.2015, 04:57
1 ответ

Предположим, что ваши ключи не содержат двоеточия или новой строки, а ваши значения не содержат новых строк:

for key in "${!MYARRAY[@]}"; do
  printf '%s:%s\n' "$key" "${MYARRAY[$key]}"
done | sort -t : -k 2n

Если вам нужно расположить ключ в порядке, заданном значениями, прочтите вывод:

IFS=$'\n'; set -f
sorted_keys=($(
    for key in "${!MYARRAY[@]}"; do
      printf '%s:%s\n' "$key" "${MYARRAY[$key]}"
    done | sort -t : -k 2n | sed 's/:.*//'))
unset IFS; set +f
4
27.01.2020, 20:40

Теги

Похожие вопросы