LINUX.ORG.RU

Помогите исправить скрипт


0

1
код[/код-bash]
#!bin\bush
size=o 
size2=0 
for filename in `find $HOME -type f` 
         do 
                size2=`stat '-t' $filename|awk '{ printf $2 }'` 
                 if [ $size -lt $size2 ]; then 
                       size="$size2" 
                       filnam="$filename" 
                 fi 
        done 
echo 
echo Полное имя файла: ${filnam##*/} 
echo Тип файла: `file -b ${filnam##*/}` 
echo Длина файла: $(( $size/1024/1024 )) мегабайт 


Этот скрипт дожен находить в домашенем каталоге файл максимального 
размера и выводить полное имя , тип файла и его размер  .

Использовал переменную IFS="\n" перед for имена стали выводится с
пробелами но при этом все слилось в одну строку , так же использовал 
двойные кавычки результат такой же . 


Последнее исправление: Sergey2012 (всего исправлений: 2)
#!/bin/bash
maxsize=0
find ~ -type f -printf "%s %p\n" | while read size name
do
 if [ $size -gt $maxsize ]
 then
  maxsize="$size"
  filename="$name"
 fi
done

echo "Путь к файлу: ${filename}"
echo "Тип файла: $(file -b "${filename}")" 
echo "Длина файла: $(( $size/(1024**2) )) мегабайт"
AITap ★★★★★
()
Ответ на: комментарий от AITap
#!/bin/bash
maxsize=0
while read size name
do
 if [ $size -gt $maxsize ]
 then
  maxsize="$size"
  filename="$name"
 fi
done < <(find ~ -type f -printf "%s %p\n")

echo "Путь к файлу: ${filename}"
echo "Тип файла: $(file -b "${filename}")" 
echo "Длина файла: $(($maxsize/(1024**2))) мегабайт"

У меня только так заработало, иначе filename недоступно за пределами цикла.

gman
()
Ответ на: комментарий от AITap

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

следственно и не работает .

anonymous
()
#!/bin/sh
cd ~/
FILE=`find ./ -type f 2> /dev/null -exec ls -s {} \; | sort -r -k 1 -n | head -n 1`
echo "File name: file "${FILE/* ./.}""
echo "File size: ${FILE/ */}"
echo "File type: `file """${FILE/* ./.}"""`"
kostik87 ★★★★★
()
Ответ на: комментарий от AITap

Я видел , у меня интернет плоховато работает , на ХР хорошо,а тут чет тормозит жутко все отлично работает !!! Огромное спасибо за сэкономленое время , а то я уже столько прочитал и ниче не помагало

anonymous
()
Ответ на: комментарий от kostik87

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

Sergey2012
() автор топика

Спасибо всем за помощь , без вас еще часа б два просидел .Теперь буду улучшать менюшку и чет подабавляю . Ище раз спасибо всем !

Sergey2012
() автор топика
Ответ на: комментарий от Sergey2012
#!/bin/sh
cd ~/
FILE=`find ./ -type f 2> /dev/null -exec ls -s {} \; | sort -r -k 1 -n | head -n 1`
echo "File name: "${FILE/* ./.}"" 
echo "File size: ${FILE/ */}"
echo "File type: `file """${FILE/* ./.}"""`"

Первая команда:
cd ~/ - переход в домашнюю директорию.

Вторая команда:
find ./ -type f 2> /dev/null -exec ls -s {} \; - получаем список файлов и для каждого найденного файла вызываем ls -s, получаем запись <размер> <имя файла>, весь вывод отправляем на сортировку.


2> /dev/null - убираем ошибки из вывода.

sort -r -k 1 -n - сортируем по убыванию (-r), указывая, что сортировать по первому столбцу (-k 1) входного потока данных, указывая, что в первом столбце числа (-n).

head -n 1 - срезаем верхнюю строку, в ней как раз и будет файл с максимальным размером.

Если в sort убрать ключ "-r", то следующая команда будет такой:
tail -n 1.

head - вывод необходимого числа строк сверху. tail - вывод необходимого числа строк снизу.
По поводу последних трёх команд посмотрите вот эту ссылку: Advanced Bash Scripting Guide операции со строками

Число ковычек в последней команде нужно для экранирования пробелов в именах файлов.

kostik87 ★★★★★
()

А вот если будет два файла с одинаковым размером , то оно ж выведет последный . Как обращатся к таким файлам ?

Sergey2012
() автор топика

> IFS=«\n»

Нормально блин, в треде так никто и не объяснил сей момент)).

«\n» в отличие от остальных языков, шелл не интерпретирует (но кавычки, скажем, экранирует и «\\» - внутренне «\»): это делает (например) встроенный или внешний echo.

Можно было: закрыть кавычки на следующей линии / $'\xa' (что не есть портабельно) / $(echo).

n01r ★★
()

Советую это на сях написать. Намного быстрее работать же будет. Тем более, учитывая специфику, сортировать не надо будет.

А с этим скриптом еще могут быть проблемы, если файлов очень много.

Вариант kostik87' совсем плохой: сортировка не нужна.

Просто рекурсивно перебираете все файлы в текущей директории и ищете файл с максимальным размером, храня в буфере путь к последнему «самому большому» файлу и его размер.

Eddy_Em ☆☆☆☆☆
()

>#!bin\bush

Такого жирного ещё не видел.

amorpher ★★★★★
()
Ответ на: комментарий от Eddy_Em

Чем вам не нравится моя сортировка и чем они отличается от простого перебора всех файлов и сравнивания размера каждого файла с тем, что лежит в буфере, по сути одно и тоже, конечно есть чуть большая нагрузка, но я сортировал sort`ом и большее число файлов, к примеру все distfiles gentoo, для отправки на утилиту comm и сравнения какие у меня файлы отсутствуют, а там примерно 65000-70000 файлов, сортировалось быстро пару секунд.

То что вы предлагаете и я предложил по сути одно и тоже.

Только я использовал уже имеющиеся стандартные средства и написано это было за пару минут. Сколько вы будете писать это же на C или к примеру ТС.

kostik87 ★★★★★
()
Ответ на: комментарий от kostik87

Посчитайте накладные ресурсы на сортировку массива из N элементов и на поиск максимального значения в этом массиве. Первое пропорционально как минимум N·log(N) (а то и N²), а второе - всего лишь пропорционально N.

Сколько вы будете писать это же на C

Не больше получаса.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Существуют разные способы сортировки, и это уж точно не «пузырь», которые достаточно быстры, я вам уже написал, что сортировал массив из 70000 элементов, утилита sort затратила на это пару секунд, дольше в моём примере займёт получение списка файлов и размера каждого файла.

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

Так что суммарное время работы моего примеру будет равно или не сильно будет отличаться от вашего примера на C, который вы собираетесь писать 30 пинут, а я свой скрипт написал за 2 минуты.

Сначала попробуйте напишите.

kostik87 ★★★★★
()
Ответ на: комментарий от kostik87

Ты написал глупость, хоть и работающую. Я даю тебе шанс самообразоваться, а ты это предложение отвергаешь. ССЗБ.

baverman ★★★
()
Ответ на: комментарий от baverman

Ну напиши пример, который ты видишь, что бы я смог «самообразоваться».

Я не отвергаю, но не вижу в чём я не прав и почему ты считаешь это глупостью.

kostik87 ★★★★★
()
Ответ на: комментарий от kostik87

Основная ошибка:

$ man ls | grep -A 1 -e '--size'
       -s, --size
              print the allocated size of each file, in blocks

allocated

in blocks

Смекаешь? К тому же дергать бинарь на каждый файл это совсем моветон. А у find есть замечательная опция -printf для таких дел.

baverman ★★★
()
Ответ на: комментарий от kostik87

Существуют разные способы сортировки

Знаю. Только вообще без сортировки быстрее.

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

Недолго: readdir, opendir, stat...

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от n01r

du -bax

в теме также никто не объяснил что достаточно du и обвязку, как-то так:
du -bax c |sort -g|tail -n5
Sergey2012 - это намёк :)

mumpster ★★★★★
()
Ответ на: xargs от mumpster

du

Хехе, так обычно и бывает, то чем пользуешься каждый день (именно для нахождения отжирателей места), почему-то забывается в совет тредах.

baverman ★★★
()
Ответ на: xargs от mumpster

Конкретно у find есть «+».

n01r ★★
()

kostik87 baverman mumpster Eddy_Em

Так как же все же лучше написать этот скрипт и какие команды при этом ипользовать ??

скрипт kostik87 работает быстрей чем у gman .

2> /dev/null - убираем ошибки из вывода.

Какие именно ошибки эта конструкция убирает ??

По каким причинам они возникают ??

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

Sergey2012
() автор топика
Ответ на: комментарий от Sergey2012

Если задача практическая, суть которой найти файлы самого большого размера, то я бы делал через du.

Если это какая-то лаба, то без разницы.

baverman ★★★
()
Ответ на: комментарий от Sergey2012
#!/bin/sh
TMP="/tmp/file.tmp"
cd ~/
find ./ -type f -printf %k" "%h\/%f\\n 2> /dev/null | sort -r -k 1 -n > $TMP
FILE=`cat $TMP | head -n 1`
FSIZE="${FILE/ */}"
echo "File size: $(($FSIZE/1024)) MB"
cat $TMP | grep "$FSIZE " | while read FILE 
do
   echo "File name: "${FILE/* ./.}"" 
   echo "File type: `file -b """${FILE/* ./.}"""`"
done

У консольных команды 3 «канала», 2 на ввод/вывод stdin и stdout и ещё один «канал», через который выводятся ошибки stderr. Ошибкой для команды find является не возможность получения доступа к файлу / директории.

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

directory drwxrw----

В данном случае просмотреть содержимое директории сможет только её владелец, утилита find выдаст ошибку на второй канал вывод, канал вывода ошибок, о том, что не может получить доступ к директории «directory».
Конструкция 2> /dev/null перенаправляет вывод ошибок на устройство /dev/null, тем самым «убирая» его с входного канала следующей команды, команда sort.

Для того, что бы выводить имена файлов с одинаковым размером пришлось ввести вывод сортированного списка файлов по их размеру в промежуточный файл, получить размер самого большого файла, первая строка в файле, выбрать из файла все строки, команда 'grep', в которых указаны файлы с таким же размером и в цикле вывести их имя и тип, размер я вывожу перед циклом 1 раз, т.к. он одинаковый.

Команда find слегка переписана по совету baverman, использовались стандартные функции утилиты find, в целях не вызывать дополнительно внешние программы, что бы не замедлять обработку, если вам что-либо не ясно почитайте 'man find', если совсем не ясно спрашивайте здесь.

Размер файла перед выводом переводится из KB (килобайт 2^10) в MB (мегабайты 2^20).

kostik87 ★★★★★
()
Ответ на: комментарий от kostik87

Спасибо за подробное разьяснение . Вы реально очень мне помогли .

Sergey2012
() автор топика
Ответ на: комментарий от kostik87

>cat $TMP | head -n 1

head -n 1 $TMP

cat $TMP | grep «$FSIZE »


grep «$FSIZE » $TMP

anonymous
()

Вот, наклепал.

Еще хочу добавить туда построение простенькой гистограммы по файлам и кое-какой статистики.

Работает довольно шустро, вот на ntfs:

max_size

Biggest file: /1.5/123 with size=51200.000MB (53687091200B)
Processed: 131542 files in 6809 directories; 0 symlinks dropped

Time of work: 97.145s
Второй запуск дал 72.873s, третий 42.864s А вот - на reiserfs:
max_size 

Biggest file: /Music/__VIDEO__/MAXIDROM_2003.avi with size=2807.682MB (2944068300B)
Processed: 30157 files in 2852 directories; 1 symlinks dropped

Time of work: 134.111s
Второй запуск дал… 0.097s (не думал, что кэширование дерева ФС так хорошо работает). Кэширование даже в процессе копирования работает:
max_size 

Biggest file: /Music/__VIDEO__/MAXIDROM_2003.avi with size=2807.682MB (2944068300B)
Processed: 30211 files in 2853 directories; 1 symlinks dropped

Time of work: 0.190s

Eddy_Em ☆☆☆☆☆
()

Спасибо за идею. Добавил простенькую гистограммку для отображения размеров файлов. Может как-нибудь на досуге еще чего добавлю.

Eddy_Em ☆☆☆☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.