Печатать имя подкаталога и содержимое файла result.txt .csv

Вы можете использовать этот скрипт из оболочки следующим образом:

$ ./transpose_csv < theinfilename > theoutfilename

И вот сценарий:

#!/usr/bin/env python
import sys, csv, itertools
rows = itertools.izip(*csv.reader(sys.stdin, delimiter=','))
sys.stdout.writelines(','.join(row) + '\n' for row in rows)
6
задан 8 December 2017 в 22:20

6 ответов

Решение скрипта Bash

#!/bin/bash # If $1 is not given, find will assume cwd print_file(){ local inputfile="$1" while IFS= read -r line || [ -n "$line" ];do printf "%s\\" "$line" done < "$inputfile" } get_file_info(){ local filepath="$1" counter=$((counter+1)) parent=${filepath%/*} if [ "$parent" = "$filepath" ]; then parent="." fi printf "%d,%s," "$counter" "$parent" } main(){ if [ -z "$1" ];then set "." fi find "$1" -type f -name "result.txt" -print0 | while IFS= read -r -d '' path do get_file_info "$path" print_file "$path" printf "\n" done } main "$@"

Как это работает, вы должны сохранить это как файл, например results2csv.sh, сделать исполняемый файл с chmod +x и запустить либо путем полного пути к сценарий или поместить его в папку ~/bin, запустите source ~/.bashrc и вызовите скрипт по имени.

Вот как работает этот скрипт:

$ ./result2csv.sh things 1,things/thing2,to be or not to be\that's Boolean logic\ 2,things/thing1,one potato\two potato\

Дайте сценарию топ- в большинстве каталогов, и он будет проходить через подкаталоги, находящие файлы, и выводит путь к файлу в соответствии с тем, как вы указали самый верхний каталог. Так, например, если вы указали ./things как наибольший, это приведет к тому, что первая строка будет иметь ./thing/things2 как путь к файлу. Новые строки заменяются обратными косыми чертами для отображения содержимого файла. Обратите внимание, что он также будет считать текущий рабочий каталог "." если каталог не указан.

$ cd things $ ../result2csv.sh 1,./thing2,to be or not to be\that's Boolean logic\ 2,./thing1,one potato\two potato\

Все, что вам нужно сделать сейчас, это вызов results2csv.sh directory > output.csv для вывода данных в файл, и вы закончили

2
ответ дан 18 July 2018 в 01:38

Я не знаю точно, как это сделать с помощью только команд терминала, но я сделал аналогичную вещь, используя скрипт python из этого потока:

https://stackoverflow.com/questions/37644441/ python-run-script-in-all-subdirectories

С этим вы можете легко добавить funcionality для записи строк в CSV-файл:

https://stackoverflow.com/ Вопросы / 37644441 / python-run-script-in-all-subdirectories для Python 2

https://docs.python.org/3/library/csv.html для Python 3 [ ! d6]

-1
ответ дан 18 July 2018 в 01:38

Ну, вот какой способ (теперь отредактированный, чтобы превратить разрывы строк в пробелы, благодаря этому ответу на Stack Overflow):

shopt -s globstar n=0; for i in **/result.txt; do sed -e ":l;N;\$!bl;s/\n/ /g; s/.*/$((++n))\. "${i%%/*}"\t&/" "$i"; done

Вы можете добавить перенаправление для записи в файл

n=0; for i in **/result.txt; do sed ":l;N;\$!bl;s/\n/ /g; s/.*/$((++n))\. "${i%%/*}"\t&/" "$i"; done > outfile

Примечания

n=0 установить переменную для инкремента shopt -s globstar Включить рекурсивное подталкивание с помощью **, чтобы найти все файлы в каталогах ниже этого (после этого отключить shopt -u globstar , или выйдите из оболочки и запустите новую). :l установите метку для этого действия N, прочитав две строки в пространстве шаблонов (это позволяет нам использовать \n) \$!, если это последняя строка файла ... нам нужно сбежать $, потому что вся команда двойного кавычка, так что оболочка может расширяться $i и т. д. Но этот $ должен быть передан без изменений sed, где это означает " последняя строка файла ". Я рекомендую использовать одиночные кавычки для скриптов sed, если вам не нужно передавать в них переменные оболочки. bl ... Вставить в метку (сделать это снова) s/old/new заменить old на new s/\n/ /g для всех символов новой строки в пространстве шаблонов (все, кроме последнего), заменить новую строку на space .* любое число любых символов (что угодно в файле) $((++n)) increment n с каждой итерацией литеральной точки цикла \. (запятые не обрабатываются специально sed, они будут напечатаны буквально) "${i%%/*}" имя первого подкаталога текущего в пути файла, с которым мы имеем дело (разделите все символы после первого /) & совпадающий шаблон из раздела поиска (что-либо в файле) -- не интерпретируют ведущие - в последующих аргументах как дополнительные флаги опций. Это предотвращает имена файлов, начинающиеся с -, которые интерпретируются как параметры. Это необязательно в этом конкретном случае, потому что мы явно ищем для result.txt, и только файлы с этим точным именем будут переданы в цикл. Однако я включил его, если кто-то должен повторно использовать этот скрипт с помощью glob.

Вот более читаемая версия, которая также более переносима (должна работать во всех версиях sed), поскольку для разделения команд используются новые строки вместо ;:

#!/bin/bash shopt -s globstar n=0 for i in **/result.txt; do sed ":l N \$!bl s/\n/ /g s/.*/$((++n))\.,"${i%%/*}",&/" -- "$i" done > outfile
5
ответ дан 18 July 2018 в 01:38

Решение скрипта Bash

#!/bin/bash # If $1 is not given, find will assume cwd print_file(){ local inputfile="$1" while IFS= read -r line || [ -n "$line" ];do printf "%s\\" "$line" done < "$inputfile" } get_file_info(){ local filepath="$1" counter=$((counter+1)) parent=${filepath%/*} if [ "$parent" = "$filepath" ]; then parent="." fi printf "%d,%s," "$counter" "$parent" } main(){ if [ -z "$1" ];then set "." fi find "$1" -type f -name "result.txt" -print0 | while IFS= read -r -d '' path do get_file_info "$path" print_file "$path" printf "\n" done } main "$@"

Как это работает, вы должны сохранить это как файл, например results2csv.sh, сделать исполняемый файл с chmod +x и запустить либо путем полного пути к сценарий или поместить его в папку ~/bin, запустите source ~/.bashrc и вызовите скрипт по имени.

Вот как работает этот скрипт:

$ ./result2csv.sh things 1,things/thing2,to be or not to be\that's Boolean logic\ 2,things/thing1,one potato\two potato\

Дайте сценарию топ- в большинстве каталогов, и он будет проходить через подкаталоги, находящие файлы, и выводит путь к файлу в соответствии с тем, как вы указали самый верхний каталог. Так, например, если вы указали ./things как наибольший, это приведет к тому, что первая строка будет иметь ./thing/things2 как путь к файлу. Новые строки заменяются обратными косыми чертами для отображения содержимого файла. Обратите внимание, что он также будет считать текущий рабочий каталог "." если каталог не указан.

$ cd things $ ../result2csv.sh 1,./thing2,to be or not to be\that's Boolean logic\ 2,./thing1,one potato\two potato\

Все, что вам нужно сделать сейчас, это вызов results2csv.sh directory > output.csv для вывода данных в файл, и вы закончили

2
ответ дан 24 July 2018 в 17:25
  • 1
    Если (поскольку OP указывает в комментариях), в каждом каталоге верхнего уровня есть только одно вхождение result.txt, тогда вы упрощаете это find */ -name 'result.txt' -printf '%H,' -exec cat {} \;, я думаю – steeldriver 7 December 2017 в 23:43

Я не знаю точно, как это сделать с помощью только команд терминала, но я сделал аналогичную вещь, используя скрипт python из этого потока:

https://stackoverflow.com/questions/37644441/ python-run-script-in-all-subdirectories

С этим вы можете легко добавить funcionality для записи строк в CSV-файл:

https://stackoverflow.com/ Вопросы / 37644441 / python-run-script-in-all-subdirectories для Python 2

https://docs.python.org/3/library/csv.html для Python 3 [ ! d6]

-1
ответ дан 24 July 2018 в 17:25
  • 1
    Хорошо ссылаться на старую работу, которую вы сделали, и Python очень приветствуется здесь, но лучше, если вы действительно адаптируете код для конкретного вопроса и опубликуете его в ответе, а не просто укажите ссылку – Sergiy Kolodyazhnyy 7 December 2017 в 23:25

Ну, вот какой способ (теперь отредактированный, чтобы превратить разрывы строк в пробелы, благодаря этому ответу на Stack Overflow):

shopt -s globstar n=0; for i in **/result.txt; do sed -e ":l;N;\$!bl;s/\n/ /g; s/.*/$((++n))\. "${i%%/*}"\t&/" "$i"; done

Вы можете добавить перенаправление для записи в файл

n=0; for i in **/result.txt; do sed ":l;N;\$!bl;s/\n/ /g; s/.*/$((++n))\. "${i%%/*}"\t&/" "$i"; done > outfile

Примечания

n=0 установить переменную для инкремента shopt -s globstar Включить рекурсивное подталкивание с помощью **, чтобы найти все файлы в каталогах ниже этого (после этого отключить shopt -u globstar , или выйдите из оболочки и запустите новую). :l установите метку для этого действия N, прочитав две строки в пространстве шаблонов (это позволяет нам использовать \n) \$!, если это последняя строка файла ... нам нужно сбежать $, потому что вся команда двойного кавычка, так что оболочка может расширяться $i и т. д. Но этот $ должен быть передан без изменений sed, где это означает " последняя строка файла ". Я рекомендую использовать одиночные кавычки для скриптов sed, если вам не нужно передавать в них переменные оболочки. bl ... Вставить в метку (сделать это снова) s/old/new заменить old на new s/\n/ /g для всех символов новой строки в пространстве шаблонов (все, кроме последнего), заменить новую строку на space .* любое число любых символов (что угодно в файле) $((++n)) increment n с каждой итерацией литеральной точки цикла \. (запятые не обрабатываются специально sed, они будут напечатаны буквально) "${i%%/*}" имя первого подкаталога текущего в пути файла, с которым мы имеем дело (разделите все символы после первого /) & совпадающий шаблон из раздела поиска (что-либо в файле) -- не интерпретируют ведущие - в последующих аргументах как дополнительные флаги опций. Это предотвращает имена файлов, начинающиеся с -, которые интерпретируются как параметры. Это необязательно в этом конкретном случае, потому что мы явно ищем для result.txt, и только файлы с этим точным именем будут переданы в цикл. Однако я включил его, если кто-то должен повторно использовать этот скрипт с помощью glob.

Вот более читаемая версия, которая также более переносима (должна работать во всех версиях sed), поскольку для разделения команд используются новые строки вместо ;:

#!/bin/bash shopt -s globstar n=0 for i in **/result.txt; do sed ":l N \$!bl s/\n/ /g s/.*/$((++n))\.,"${i%%/*}",&/" -- "$i" done > outfile
5
ответ дан 24 July 2018 в 17:25
  • 1
    есть ли способ, если файл является многострочным? – user8109 7 December 2017 в 23:14
  • 2
    файл result.txt не слишком большой. Я хочу, чтобы он заполнял только одну ячейку – user8109 7 December 2017 в 23:19
  • 3
    имя подпапки в первом столбце и вывод уникального файла result.txt mutltiline вложенной папки в следующем столбце. Один файл result.txt должен заполнять только 1 ячейку. – user8109 7 December 2017 в 23:24
  • 4
    @Zanna Просто удалите разрывы строк. Это то, что я сделал бы. – Sergiy Kolodyazhnyy 7 December 2017 в 23:27
  • 5
    @Zanna Если есть кто-то, кто может понять это через sed, это вы :) Потому что вы потрясающий – Sergiy Kolodyazhnyy 7 December 2017 в 23:31

Другие вопросы по тегам:

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