Intereting Posts
Возможно ли открыть TCP-туннель в Linux в качестве специального символьного устройства? Прямая загрузка прошивки для Ath10k не удалась Qualcomm Atheros QCA9377 Как создать относительную символическую ссылку, совместимую с POSIX, в / bin / sh? Как бы я запустил эту команду? Захват в переменных оболочки аргументов после команды (между скобками) Входной разделитель `read` встроен в Bash Как подсчитать аналогичные результаты в нескольких столбцах в Libre Office Calc? не повлияет ли когда-либо изменение аффинности на потоки ядра Linux отрицательно на общую производительность? Включение привязок клавиш Switches Viewport Switcher Прочтите файлы snort.u2 Отключение OpenVPN для каждого временного интервала Каков правильный способ автоматизации SSH / локальной команды? Как «git pull» съел мою домашнюю работу? Лучший язык для написания услуг linux KEY_CONFIG указывает на неправильную версию openssl.cnf

Использование awk для обработки вывода ls с пробелами в именах файлов / пути

Все,
У меня есть сценарий, в котором я использую команду find, чтобы отфильтровать все png-файлы в данной папке и перечислить их вместе с их размером. Я хочу, чтобы результат был в следующем формате:

someFile.png => 1.2K 

Я использую awk для получения $ 5 (размер файла в удобном для пользователя формате) и $ 9 (путь). Вот что я сейчас использую:

  find "$somePath" -iname "*.png" -print0 | xargs -0 ls -lh | awk '{print $9,"=>",$5}' 

Иногда имена файлов или пути имеют пробелы, и это отключает скрипт. Вот пример вывода:
/ Пользователи / test / Desktop / Test / image1 => 1.2K
/Users/test/Desktop/Test/image1.png => 1.4K

Первая запись на выходе – это файл с именем «image1 test.png». Я где-то читал, что не следует разбирать вывод ls. Каков наилучший способ справиться с этим?

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

 find "$somePath" -iname "*.png" -printf '%p => %s\n' 

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

 find "$somePath" -iname "*.png" -exec printf '{} => ' \; -exec sh -c 'ls -sh "{}" | cut -f1 -d\ ' \; 

Обратите внимание: последний синтаксический анализ ls , но, насколько я знаю, невозможно отобразить пробел в первом столбце; так как мы только принимаем первый столбец здесь, и потому что мы работаем с одной записью за раз (а не списком), все в порядке. В противном случае вы можете использовать другую программу для отображения размера. В BSD и Linux вы можете использовать stat ; на Solaris вам может потребоваться написать собственную программу для вывода только размера файла.

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

Самый удобный способ – использовать printf из find, но он не совсем тот вариант, который вы ищете. % k печатает размер в K, но размер, выделенный на диске, поэтому в зависимости от ваших настроек это может быть всегда кратным 4k (например, в моей системе) или что-то подобное:

 find -name "C*.png" -printf "%f => %k \n" CalculatorVergleich.png => 28 ClassifierImage.png => 8 ClassifierImage.png => 8 

Существует опция с размером в байтах:

 find -name "C*.png" -printf "%f => %s \n" CalculatorVergleich.png => 26256 ClassifierImage.png => 6313 ClassifierImage.png => 6473 

И есть% b для занятых блоков 512b:

 find -name "C*.png" -printf "%f => %b \n" CalculatorVergleich.png => 56 ClassifierImage.png => 16 ClassifierImage.png => 16 

Может быть, это полезно для вас? У него не должно быть проблем с пробелами в именах файлов.

Я предполагаю, что вы хотите использовать awk для обработки ls -l для получения дополнительной информации, которую предоставляет ls -l. В общем, find и stat дают более воспроизводимый результат, но не стесняйтесь использовать ls.

Одна из приятных вещей, которую делает ls -l, имеет фиксированную ширину, поэтому вы можете использовать substr для начала строки, а затем не указывать длину, которая будет содержать все символы до конца строки.

В приведенном ниже примере я назначаю имя файла строке, а затем заменяю пробелы символами подчеркивания. Я обычно выполняю дальнейший анализ с помощью awk, поэтому очистка пробелов от имен файлов облегчает анализ, а конечный результат – людям.

 $ ls -al | awk '{myfilename=substr($0, 57);gsub(/ /,"_",myfilename);print myfilename}' 

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

 myPath="./" find "$myPath" -type f -print0 | xargs -0 stat -c"%W %w %Y %y %X %x %9s %n" > myTemp.txt cat myTemp.txt | awk '{myfilename=substr($0, 152);gsub(/ /,"_",myfilename);printf "%s %s %12s %s\n", $6,$10,$13,myfilename}' 

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

 | sort -k 4