Я использую сценарий Awk для разделения большого текстового документа на независимые файлы. Я сделал это, и теперь я работаю с текстовыми файлами размером 14k. Проблема здесь в том, что есть много файлов всего с тремя строками текста, и мне бесполезно их хранить.
Я знаю, что могу удалять строки в тексте с помощью awk 'NF>=3' file, но я не хочу удалять строки внутри файлов, а хочу удалять файлы, содержимое которых состоит всего из двух или трех строк текста.
Заранее спасибо.
Да, полностью. Проблема в том, что у меня было много проблем с запуском скрипта, и мне приходилось несколько раз изменять его, чтобы извлечь все файлы, которые я хотел. Это не самое элегантное решение, но да ладно. В любом случае, решение, которое дал мне RavinderSigh, решило все мои проблемы.





Вы можете использовать wc для расчета строк, а затем решить, удалять файл или нет. вам следует написать сценарий оболочки, а не просто команду awk.
Не могли бы вы попробовать выполнить команду find. (Проверено с помощью GNU awk)
find /your/path/ -type f -exec awk -v lines=3 'NR>lines{f=1; exit} END{if (!f) print FILENAME}' {} \;
Таким образом, выше будут напечатаны имена файлов, которые имеют менее 3 строк на консоли. Как только вы будете довольны полученными результатами, попробуйте удалить их. Только после того, как вы согласитесь с выводом вышеприведенной команды, запустите следующий и даже Я предлагаю сначала запустить приведенную ниже команду в тестовом каталоге, и как только вы будете полностью удовлетворены, перейдите к приведенной ниже. (удалите echo снизу, я все еще поставил его для более безопасной стороны :))
find /your/path/ -type f -exec awk -v lines=3 'NR>lines{f=1; exit} END{exit !f}' {} \; -exec echo rm -f {} \;
END {} всегда выполняется, даже если скрипт завершается exit. Итак, все имена файлов напечатаны. Во всяком случае, выходной статус работает.
@ Wiimm, спасибо, что сообщили мне, я уже исправил это.
@Ed Morton, ИМХО, причина установки NR==3, поскольку OP сказал менее 3 строк, и я считаю, что когда мы используем NR>3, для удаления могут потребоваться файлы, в которых также есть 3 строки, пожалуйста, поправьте меня, если я здесь ошибаюсь. Спасибо за как всегда ваше руководство :)
OP хочет удалить файлы, содержащие строки 3 или меньше, а не менее 3 строк. Рассмотрим ваш первый сценарий. Если NR становится равным 4, тогда f устанавливается равным 1, и сценарий завершается без печати FILENAME. Если NR никогда не достигает 4 (т. е. 3 или меньше), то f никогда не устанавливается, и поэтому сценарий печатает FILENAME. Это именно то, что вы хотите, поскольку вы пытаетесь создать список файлов для удаления. Аналогичная логика для вашего второго скрипта.
@EdMorton, конечно, Эд, сэр, понял, спасибо за хорошее объяснение, хороших выходных впереди :)
Хорошо, это решение решило все мои проблемы. Это сработало отлично! И да, я хотел удалить все файлы, содержащие 3 или менее строк. Я изменил сценарий, чтобы увидеть, какой из них решил его удовлетворительным образом, и вуаля, все мои проблемы исчезли :D. Большое тебе спасибо!
Если все файлы в текущем каталоге являются текстовыми файлами, это должно быть эффективным и переносимым:
for f in *; do
[ $(head -4 "$f" | wc -l) -lt 4 ] && echo "$f"
done # | xargs rm
Просмотрите список и, если он выглядит нормально, удалите # в последней строке, чтобы фактически удалить ненужные файлы.
Зачем использовать head -4? Потому что wc не знает, когда остановиться. Предположим, что половина текстовых файлов имеет размер более терабайта каждый; если бы это было так, один только wc -l был бы довольно медленным.
Вы можете попробовать Перл. Приведенное ниже решение будет эффективным, поскольку дескриптор файла ARGV будет закрыт, если количество строк > 3.
perl -nle ' close(ARGV) if ($.>3) ; $kv{$ARGV}++; END { for(sort keys %kv) { print if $kv{$_}>3 } } ' *
Если вы хотите передать вывод какой-либо другой команды (скажем, найти), вы можете использовать ее как
$ find . -name "*" -type f -exec perl -nle ' close(ARGV) if ($.>3) ; $kv{$ARGV}++; END { for(sort keys %kv) { print if $kv{$_}>3 } } ' {} \;
./bing.fasta
./chris_smith.txt
./dawn.txt
./drcatfish.txt
./foo.yaml
./ip.txt
./join_tab.pl
./manoj1.txt
./manoj2.txt
./moose.txt
./query_ip.txt
./scottc.txt
./seats.ksh
./tane.txt
./test_input_so.txt
./ya801.txt
$
вывод wc -l * в том же каталоге
$ wc -l *
12 bing.fasta
16 chris_smith.txt
8 dawn.txt
9 drcatfish.txt
3 fileA
3 fileB
13 foo.yaml
3 hubbs.txt
8 ip.txt
19 join_tab.pl
6 manoj1.txt
6 manoj2.txt
5 moose.txt
17 query_ip.txt
3 rororo.txt
5 scottc.txt
22 seats.ksh
1 steveman.txt
4 tane.txt
13 test_input_so.txt
24 ya801.txt
200 total
$
Не было бы разумнее изменить существующий скрипт, чтобы он просто не создавал файлы с 3 или менее строками?