Linux "для" построить в кш - PullRequest
       3

Linux "для" построить в кш

0 голосов
/ 02 августа 2010

Обычно я использую конструкцию for в ksh для быстрой итерации по списку файлов для выполнения каких-либо действий с ним.Кажется, он не работает в этом сценарии:

The file info looks like: 
$ ls -l tmp.*  
rw------- 1 op general 375 Jul 25 04:09 tmp.zzyhsg4  
...  
so on. Basically a lot of tmp.* files.    

Now when I try  
$ ls -lS | grep 'Jul 25' | grep 'tmp.*' | cut -d' ' -f9 | more  
tmp.zzyhsg4  
..  

он будет печатать только имена файлов, как и ожидалось.Однако, когда я пытаюсь описать следующее

$ for i in `ls -lS | grep 'Jul 25' | grep 'tmp.*' | cut -d' ' -f9`
>do  
>echo $i  
>done  

, здесь не печатаются имена всех файлов, начиная с tmp. *, Которые были созданы 25 июля, отсортированные по размеруОн печатает размер столбца.Интересно, что если я заменю f10 на f6 для сокращения, он правильно напечатает столбец месяца.Он начинает ломаться после f9.

Есть идеи?

Ответы [ 2 ]

1 голос
/ 02 августа 2010

Я не могу воспроизвести точно то, что вы описываете, но у меня есть несколько предложений по написанию более надежных команд.

cut -d' ' разделяет поля пробелами.Если у вас есть два пробела подряд, между ними есть пустое поле.Поэтому, если вы попытаетесь использовать Aug 1 вместо Jul 25, столбец с именем файла будет смещен на 1. А если вы попытаетесь использовать файлы, возраст которых превышает 6 месяцев, то время (5 символов) будет заменено пробеломк 4-значному году.Кроме того, в зависимости от вашей версии ls между столбцами может быть несколько пробелов.Еще одна проблема заключается в том, что некоторые версии ls не отображают столбец group.И тогда некоторые имена файлов содержат пробелы.И некоторые имена файлов содержат специальные символы, которые ls могут отображаться как ?.Таким образом, вы не можете проанализировать вывод ls -l путем подсчета пробелов, и вы даже не можете проанализировать вывод ls -l путем подсчета полей, разделенных пробелами.Просто не анализирует вывод ls .

Стандартная команда для генерации списков имен существующих файлов - find.Поскольку вы упоминаете Linux, я упомяну опции, которые работают с GNU find (версия, которую вы получаете для Linux), но не для других unixes.

Давайте начнем с простого: перечислим файлы с именем tmp.* в текущем каталоге.

find . -name 'tmp.*'

Нам нужны только файлы, созданные 25 июля, то есть 7 дней назад.

find . -name 'tmp.*' -daystart -mtime 7

Это хрупкий файл, потому что он не будет работать завтра.Обычный способ указать точную дату - создать файлы с самой ранней и самой поздней допустимой датой и указать find возвращать только файлы с этими двумя значениями.

touch -t 201007250000 .earliest
touch -t 201007260000 .latest
find . -name 'tmp.*' -newer .earliest \! -newer .latest
rm .earliest .latest

Команда find исследует подкаталогирекурсивно.Если вы не хотите этого:

find . -name 'tmp.*' -daystart -mindepth 1 -maxdepth 1 -mtime 7

Если вы хотите, чтобы файлы сортировались по размеру:

find . -name 'tmp.*' -daystart -mtime 7 -printf '%s\t%p\n' | sort -n -k 1 | cut -f 2-

Наконец, если вы хотите работать с файлами, никогда используйте find в обратных тегах, как вы использовали ls, потому что это не удастся, если имена файлов содержат пробел или некоторые специальные символы, потому что оболочка разделяет вывод `command` на пробел, а затем выполняет глобализациюрезультирующие слова.Вместо этого используйте параметр -exec для find;версия ; выполняет mycommand один раз для файла с {}, замененным именем файла, тогда как версия + обычно вызывает mycommand только один раз с {}, замененным списком имен файлов.

find . -name 'tmp.*' -daystart -mtime 7 -exec mycommand -myoption {} \;
find . -name 'tmp.*' -daystart -mtime 7 -exec mycommand -myoption {} +
1 голос
/ 02 августа 2010

Чтобы получить все файлы с именем tmp.*, используйте

$ ls -lS tmp.*

С разрезом вы говорите, чтобы взять пробел в качестве разделителя. Это не будет работать должным образом. Количество пробелов между полями является гибким, поэтому у вас будет различное количество полей. (между каждыми 2 пробелами у вас будет пустое поле)

Лучше использовать find, который может сформировать ваш список файлов в любой форме:

$ find tmp.* -printf "%s %CD %f\\n" | grep "07/25/10" | sort -n

(man find, чтобы также получить фильтрацию даты в команде find)

...