Пакетное свертывание текстовых файлов с помощью bash-скрипта

831
Frank_Zafka

Мне трудно делать что-то довольно простое. У меня есть около 2000 файлов .txt, которые состоят из одной строки цифр. Я хотел бы сложить одну строку в один столбец с несколькими строками, используя команду сгиба, и перезаписать исходный файл этой новой свернутой версией. Моя попытка:

#!/bin/bash for i in *.txt ; do fold -w 1 $file > $file done 

Не работает Помогите? Благодарю.

2
Чтобы избежать необходимости непосредственно обрабатывать и очищать временные файлы, см. «Sponge» из пакета «moreutils» в [«Редактирование файлов на месте»] (http://backreference.org/2011/01/29). / в месте редактирования, из-файлов /), Peter.O 11 лет назад 0

2 ответа на вопрос

5
terdon

Здесь есть две проблемы. Во-первых, вы объявляете переменную «i», но используете «$ file», который не существует. Даже если это произойдет, вторая проблема заключается в том, что bash читает «слева направо». Это означает, что он сначала увидит «> $ file» и перезапишет содержимое файла. Поэтому, если бы вы использовали правильные переменные, вы бы потеряли свои данные.

Итак, одна ошибка спасла вас от другой, вы счастливчик, счастливчик :)

Попробуйте что-то вроде:

for i in *.txt ; do fold -w 1 $i > sillytmpfile; mv sillytmpfile $i; done 
В мою защиту у меня грипп. Попробую. Просто из любопытства. У меня есть 18 ГБ текстовых файлов. Любой способ сделать это без временного файла? Благодарю. Frank_Zafka 11 лет назад 0
@RSoul tmpfile создается один раз для каждого файла и удаляется немедленно, не должно вызывать проблем. Единственный способ сделать это без файла tmp - перенаправить сложенный вывод в другой файл: `for i in * .txt; do fold -w 1 $ i> $ i ".folded"; done`. Это, однако, удвоит количество файлов, и я бы не рекомендовал это. terdon 11 лет назад 1
Хорошо. Вся часть кривой обучения. :) Frank_Zafka 11 лет назад 0
Вы можете оптимизировать его, если выберете путь для `sillytmpfile` на виртуальном диске. В Linux это обычно `/ tmp`,` / run / shm`, возможно, другие, проверьте с помощью `mount | grep tmpfs`. Thor 11 лет назад 0
2
Thor

sed может также быть опцией, это обрабатывает проблему временного файла внутренне:

for i in *.txt ; do sed -i 's#.#&\n#g' $file done 
Интересно. Я однажды найду понимание сед. ;) Frank_Zafka 11 лет назад 0
Тем не менее, создает файл TMP, хотя. И мое * предположение * это займет немного больше времени, так как он имеет регулярное выражение для оценки и будет искать его во всей строке. terdon 11 лет назад 0
Да, это определенно медленнее, попробуйте это с `fold` и` sed` ... `time printf '% sabcdef \ n' | fold -w 1> / dev / null` ... Кроме того, вывод ** отличается ** из-за способа обработки оригинальных строк новой строки. Peter.O 11 лет назад 1
@PeterO: Примерно в 6 раз медленнее по моим измерениям, но я не получаю никакой разницы в выходе. Thor 11 лет назад 0
Может быть, это проблема версии. Вот мои команды и результаты подсчета строк `wc`: ... *** fold *** * (GNU coreutils) 7.4 *` printf '% sabcdef \ n' | fold -w 1 | wc -l # -> 11888896` ... * GNU * *** sed *** * версия 4.2.1 * `printf '% sabcdef \ n' | sed 's #. # & \ n # g '| wc -l # -> 12888896` Peter.O 11 лет назад 0
Ах, я вижу, `sed` включает в себя новые строки из ввода в выводе, я пропустил это раньше, потому что мой` diff` игнорирует пробелы. Итак, `printf '% sabcdef \ n' | tr -d '\ n' | sed 's #. # & \ n # g' | wc -l # -> 11888896`. Но, как уже отмечалось, `fold '- лучший выбор для OP. Thor 11 лет назад 0