Как я могу перечислить файлы в обратном порядке по команде и передать их в качестве аргументов другой команде?

Используйте yes >> foo вместо yes > foo и отдельно : >foo для очистки файла

yes >> foo вызывают read для открытия foo с O_APPEND. Это заставляет смещение файла позиционироваться в конец файла перед каждой записью.

Итак, yes записывает в файл foo, причем каждая запись приводит к позиционированию указателя файла в конец foo. Тем временем : > foo усекает файл до 0 байт. Теперь следующая запись yes, из-за перестановки указателя файла в "конце" нулевого байта foo, вызванной O_APPEND, начинается с начала нулевого байта foo

7
22.04.2019, 16:54
3 ответа
(IFS=$'\n'; set -f; your_program $(ls -tr))

Предполагается, что имена файлов не содержат символов новой строки.

Пример:

% touch 'a   b'
% touch 'c d'
% touch '*'
% (IFS=$'\n'; set -f; printf '%s\n' $(ls -tr))
e    f
a   b
c d
*

Вариант для стандартной оболочки, которая не поддерживает $'...'строки:

(IFS='
' ; set -f; your_program $(ls -tr))

Простая оболочка Python, которая будет работать даже с именами файлов, содержащими символы новой строки. Использование может быть this_wrapper your_program *.

#! /usr/bin/python
import os
import sys

sys.argv[2:] = sorted(sys.argv[2:], key=os.path.getmtime)
os.execvp(sys.argv[1], sys.argv[1:])
3
27.01.2020, 20:16

Если у вас достаточно обновленные версии утилит GNU с -по -даты, вы можете настроить их на обработку данных с завершением NULL -. Это позволяет создавать конвейеры, на которые не влияют пробелы или символы новой строки в самих данных.

Мой тестовый инструмент — это быстрый скрипт под названием/tmp/args:

#!/bin/bash
echo "This is args with $# value(s)"
for f in "$@"; do echo "> $f <"; done

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

find -type f -printf "%T@ %p\0" | sort -zn | sed -z 's/^[0-9.]* //' | xargs -0 /tmp/args

Команда findставит перед каждым именем файла/пути представление в долях секунды даты/времени последнего изменения. Это обрабатывается sortв порядке от самого низкого (самого старого )до самого высокого (самого нового ). sedудаляет начальное число, которое мы только что использовали для сортировки, и результирующий набор имен файлов передается в xargs. Замените %pна %P, если вы предпочитаете опускать начальный ./в именах файлов.

Пример данных

# "c d" contains a space; "e f" contains a newline; "h" has leading whitespace
touch a 'e
f' g ' h ' 'c d' b

Пример результата

This is args with 6 value(s)
>./a <
>./e
f <
>./g <
>./ h  <
>./c d <
>./b <
5
27.01.2020, 20:16

Bash еще не позволяет легко сортировать файлы по времени модификации , поэтому вот обязательный ответ, основанный на zsh -. Вам не нужно переключаться на zsh в качестве оболочки для входа в систему, чтобы использовать ее функции.

Здесь я настроил функцию-оболочку, которая принимает один или два аргумента; первый аргумент - это программа для выполнения (, например.myprogram); второй необязательный аргумент — это каталог, содержащий файлы, которые вы хотите передать программе. Если вы не укажете второй аргумент, по умолчанию используется текущий каталог.

zeio() {
  # Zsh-based Execute with files In Order
  [ -d "${2:-.}" ] || return
  zsh -c "$1 \"${2:-.}\"/*(.om)"
}

Назовите это как хотите, конечно. После быстрой проверки -второго аргумента (еще раз, по умолчанию ., текущий каталог ),мы вызываем zsh с одной строкой в ​​двойных -кавычках, которая содержит программу и некоторые начальные аргументы (аргумент #1 )и каталог (аргумент #2 )— по умолчанию .— с расширением подстановочного знака/шаблона, которое имеет два «квалификатора подстановки» в конце круглых скобок:

  1. .--должны быть обычные файлы (не каталоги или символические ссылки и т. д.)
  2. om--order (сортировать )результирующий список по времени модификации, сначала самые последние

Именно этот квалификатор omglob делает здесь всю реальную работу.

Вот несколько примеров прогонов; myprog— это простой сценарий оболочки для демонстрации аргументов, которые он получает, чтобы:

#!/bin/sh
for arg do
  printf 'Arg: ->%s<-\n' "$arg"
done

и go.sh— это файл, в котором я сохранил функцию. Остальная часть структуры каталогов:

$ tree.
.
├── dir1
│   ├── 203142
│   ├── 203143
│   └── 203144
├── dir3
│   ├── first\012filename
│   ├── this is 3rd
│   └── this is second
├── dir two
│   ├── 203225
│   ├── 203226
│   └── 203227
├── go.sh
└── myprog

... где я создал наборы из трех файлов в каждом подкаталоге в указанной последовательности; Я ожидаю увидеть их в том же порядке при выполнении функции. Имя первого файла в каталоге dir3 содержит новую строку, представленную treeс \012. Результаты:

Демонстрация поведения по умолчанию -- -текущего -каталога:

$ zeio./myprog
Arg: ->./myprog<-
Arg: ->./go.sh<-

Демонстрация нормального имени файла

$ zeio./myprog dir1
Arg: ->dir1/203142<-
Arg: ->dir1/203143<-
Arg: ->dir1/203144<-

В каталоге есть пробел

$ zeio./myprog "dir two"
Arg: ->dir two/203225<-
Arg: ->dir two/203226<-
Arg: ->dir two/203227<-

в именах файлов есть пробелы

$ zeio./myprog dir3
Arg: ->dir3/first
filename<-
Arg: ->dir3/this is second<-
Arg: ->dir3/this is 3rd<-
4
27.01.2020, 20:16

Теги

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