Объединение файлов в каталоге и определение общего количества строк

В bash:

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

! cat /data/files *.txt >> mergedfile.txt | wc -l ~/data/files/mergedfile.txt

Однако, похоже, это не работает. Я использую bash и работаю в iPython (таким образом, впереди!).

0
11.09.2017, 04:11
2 ответа

Ваш вопрос немного искажен:

  • Вы используете !для представления командной строки? Это нетипично.
  • Вы говорите обо всех .txtфайлах в каталоге /data/files? Для этого нужно сказать /data/files/*.txt. Если вы имеете в виду что-то другое под /data/files *.txt, пожалуйста, объясните это.
  • >> mergedfile.txtбудет добавлять файлы к mergedfile.txt, если он уже существует. Это то, что вы хотите? Если вы хотите что-то подобное, вы должны сказать об этом в своем вопросе.

Во всяком случае, как сказано Arrow в комментарии , простое и очевидное решение — заменить |на ;,вот так:

$ cat /data/files/*.txt >> mergedfile.txt; wc -l mergedfile.txt

Примечания:

  • Как я уже говорил выше, >>добавляет файлы в mergedfile.txt, если он уже существует. Если вы хотите игнорировать (, отбросить )любое предыдущее содержимое mergedfile.txt, используйте >вместо >>.
  • Если вы собираетесь ссылаться на один и тот же файл несколько раз, вы должны делать это одинаково каждый раз. Использование относительного пути один раз и абсолютного пути в следующий раз сбивает с толку и подвержен ошибкам -. (Возможно, вы захотите что-то упростить путем присвоения имени файла переменной.)

Небольшое улучшение по сравнению с предыдущим:

$ cat /data/files/*.txt > mergedfile.txt  &&  wc -l mergedfile.txt

с &&вместо ;. Это приводит к выполнению команды wc -l. только если команда catвыполнена успешно.

Каждая из приведенных выше командных строк характеризуется как «список команд», содержащий два «конвейера» (, хотя на самом деле конвейеры не задействованы ). Если вы хотите сделать это как единый «конвейер», сделайте это:

$ cat /data/files/*.txt | tee mergedfile.txt | wc -l

который подсчитывает строки при объединении файлов, избавляя от необходимости читать выходной файл. Если вы хотите добавить к существующему mergedfile.txt, используйте tee -a.

0
28.01.2020, 04:40

Так и должно быть:

! cat /data/files/*.txt >> mergedfile.txt && wc -l /data/files/mergedfile.txt

Ваши команды состоят из двух команд -первый — cat, который выводит в текстовый файл путем перенаправления -второй — вычислить длину результирующего файла

Эти две команды должны выполняться последовательно при условии, что первая успешно выполнена. Итак, вы используете &&для цепочки. После перенаправления stdoutиз catна mergedfile.txtкоманда catне создает stdoutдля трубопровода на wc. Поэтому использовать |неправильно.

В качестве альтернативы вы можете:

! cat /data/files/*.txt | wc -l

, который является более кратким и позволяет избежать использования временного файла. Здесь вывод catотправляется в wcдля непосредственного подсчета.

Обратите внимание , первый подход с использованием временного файла имеет много недостатков:

  • вам нужно очистить файл mergedfile.txtперед его выполнением. Если вы начали без этого файла в своем рабочем каталоге, это нормально. Но очень часто вы пробовали некоторые команды (, например не ту, которую вы использовали сначала ), а затем забывали очистить временный файл и запустить правильную команду. Это все равно приведет к неправильному ответу. Действительно, если все строки находятся в /data/files/*.txt, вы можете просто использовать >вместо >>. Сначала он очистит файл.
  • Во время выполнения команды временный файл может быть изменен другими пользователями или вами, когда вы хотите сделать что-то параллельно.

Кроме того :, если вам нужно mergedfile.txtдля последующего использования, вы можете использовать tee, чтобы сделать копию вывода:

! cat /data/files/*.txt | tee mergedfile.txt | wc -l

где teeпомещает свой stdinв mergedfile.txtи дублирует его в stdout.

0
28.01.2020, 04:40

Теги

Похожие вопросы