Используйте имя папки как столбец в текстовом файле - PullRequest
5 голосов
/ 23 февраля 2012

Ленивый я думает о добавлении столбца в некоторые текстовые файлы.

Текстовые файлы находятся в каталогах, и я хотел бы добавить имя каталога в текстовый файл.

Как и текстфайл text.txt в папке the_peasant:

has a wart    
was dressed up like a witch     
has a false nose

станет:

the_peasant has a wart    
the_peasant was dressed up like a witch    
the_peasant has a false nose

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

Я бы подумал, что это комбинация команды find, сценариев bash и sed, но я не могу ее увидеть.Есть идеи?

Ответы [ 9 ]

3 голосов
/ 23 февраля 2012

Это может работать для вас:

find . -name text.txt | sed 's|.*/\(.*\)/.*|sed -i "s@^@\1 @" & |' | sh

или если у вас есть GNU sed:

find . -name text.txt | sed 's|.*/\(.*\)/.*|sed -i "s@^@\1 @" & |e' 
1 голос
/ 23 февраля 2012

Обязательный однострочник с использованием find и perl

find . -maxdepth 1 -mindepth 1 -type d | perl -MFile::Basename -ne 'chomp; my $dir = basename($_); for my $file (glob "$dir/*") { print qq{sed -i "s/^/$dir /" $file\n} }' | tee rename_commands.sh

sh rename_commands.sh

Предполагается, что perl и sed находятся в вашем $ PATH.Создает файл команд sed для внесения реальных изменений, чтобы вы могли просмотреть, что нужно сделать.

В моем тесте этот командный файл выглядит так:

sed -i "s/^/foo /" foo/text1
sed -i "s/^/foo /" foo/text2
sed -i "s/^/bar /" bar/belvedere
sed -i "s/^/bar /" bar/robin
1 голос
/ 23 февраля 2012

Дерево каталогов:

% tree .
.
├── the_king
│   └── text.txt
├── the_knight
│   └── text.txt
├── the_peasant
│   └── text.txt
└── wart.py
3 directories, 4 files

Каталоги и содержимое до:

% find . -name 'text.txt' -print -exec cat {} \;       
./the_king/text.txt
has a wart    
was dressed up like a witch     
has a false nose
./the_knight/text.txt
has a wart    
was dressed up like a witch     
has a false nose
./the_peasant/text.txt
has a wart    
was dressed up like a witch     
has a false nose

Код (wart.py):

#!/usr/bin/env python

import os

text_file = 'text.txt'
cwd = os.path.curdir # '.'

# Walk thru each directory starting at '.' and if the directory contains
# 'text.txt', print each line of the file prefixed by the name containing
# directory.
for root, dirs, files in os.walk(cwd):
    if text_file in files: # We only care IF the file is in this directory.
        print 'Found %s!' % root
        filepath = os.path.join(root, text_file) # './the_peasant/text.txt'
        root_base = os.path.basename(root)       # './the_peasant' => 'the_peasant'
        output = ''
        with open(filepath, 'r') as reader:      # Open file for read/write
            for line in reader:                  # Iterate the lines of the file
                new_line = "%s %s" % (root_base, line)
                print new_line,
                output += new_line               # Append to the output

        with open(filepath, 'w') as writer:
            writer.write(output)                 # Write to the file

        print

Какие выходные данные:

Found ./the_king!
the_king has a wart    
the_king was dressed up like a witch     
the_king has a false nose

Found ./the_knight!
the_knight has a wart    
the_knight was dressed up like a witch     
the_knight has a false nose

Found ./the_peasant!
the_peasant has a wart    
the_peasant was dressed up like a witch     
the_peasant has a false nose

Каталоги и содержание после:

% find . -name 'text.txt' -print -exec cat {} \;
./the_king/text.txt
the_king has a wart    
the_king was dressed up like a witch     
the_king has a false nose
./the_knight/text.txt
the_knight has a wart    
the_knight was dressed up like a witch     
the_knight has a false nose
./the_peasant/text.txt
the_peasant has a wart    
the_peasant was dressed up like a witch     
the_peasant has a false nose

Это было весело!Спасибо за вызов!

1 голос
/ 23 февраля 2012

Вот то, что я придумал:

find /path/to/dir -type f | sed -r 'p;s:.*/(.*)/.*:\1:' | xargs -n 2 sh -c 'sed -i "s/^/$1 /" $0'

Вот пример того, как команды были бы построены, предполагая, что существуют следующие файлы:

/home/the_peasant/a.txt
/home/the_peasant/b.txt
/home/the_peasant/farmer/c.txt

Первый find /home/the_peasant -type f выведет эти файлы точно так же, как указано выше.

Затем команда sed выведет имя файла, а затем имя каталога, например:

/home/the_peasant/a.txt
the_peasant
/home/the_peasant/b.txt
the_peasant
/home/the_peasant/farmer/c.txt
farmer

Xargs будет группировать каждые дваи передайте их команде sh, чтобы в итоге вы получили следующие три команды:

$ sh -c 'sed -i "s/^/$1 /" $0' /home/the_peasant/a.txt the_peasant
$ sh -c 'sed -i "s/^/$1 /" $0' /home/the_peasant/b.txt the_peasant
$ sh -c 'sed -i "s/^/$1 /" $0' /home/the_peasant/farmer/c.txt farmer

И, наконец, это приведет к следующим командам sed, которые будут добавлять имя папки в начало каждогострока:

$ sed -i "s/^/the_peasant /" /home/the_peasant/a.txt
$ sed -i "s/^/the_peasant /" /home/the_peasant/b.txt
$ sed -i "s/^/farmer /" /home/the_peasant/farmer/c.txt
1 голос
/ 23 февраля 2012

Простой скрипт на Python для этого (должен работать из любой папки, если вы, очевидно, передаете полный путь к целевому файлу):

#!/usr/bin/python
if __name__ == '__main__':
    import sys
    import os

    # Get full filepath and directory name
    filename = os.path.abspath(sys.argv[1])
    dirname = os.path.split(os.path.dirname(filename))[1]

    # Read current file contents
    my_file = open(filename, 'r')
    lines = my_file.readlines()
    my_file.close()

    # Rewrite lines, adding folder name to the start
    output_lines = [dirname + ' ' + line for line in lines]
    my_file = open(filename, 'w')
    my_file.write('\n'.join(output_lines))
    my_file.close()
0 голосов
/ 23 февраля 2012

Вот один вкладыш в bash и awk:

find . -type f -print0 |
while read -r -d "" path; do
  mv "$path" "$path.bak"
  awk -v dir="$(basename "$(dirname "$path")")" '{print dir, $0}' "$path.bak" > "$path"
done
0 голосов
/ 23 февраля 2012

Редактировать: заметил, что что-то не так.Я удалил петлю режиссуры - теперь она рекурсивно гуляет.Простите за перепутывание.

Использование os.walk

import os.path
directory = os.path.curdir
pattern = ".py";
for (path,dirs,files) in os.walk(directory):
    for file in files:
        if not file.endswith(pattern):
            continue
        filename = os.path.join(path,file)
        #print "file: ",filename
        #continue
        with open(filename,"r") as f:
            for line in f.readlines():
                print "{0} {1}".format(filename,line)
            f.close()

Вывод:

list1.py   # LAB(replace solution)
list1.py   # return
list1.py   # LAB(end solution)
0 голосов
/ 23 февраля 2012

Вы запускаете скрипт в соответствующей папке? Затем вы можете использовать модуль OS, чтобы найти текущую папку. Скажем, вы хотите взять только конец дерева каталогов, вы можете использовать os.path, например:

import os, os.path

curDirectory = os.getcwd()
baseDir = os.path.basename()

inFile = open("filename.txt").xreadlines()
outFile = open("filename.out", "w")

for line in inFile:
    outFile.write("%s %s" % (baseDir, line))
outFile.close()
0 голосов
/ 23 февраля 2012

Я бы.

  • получить путь к файлу, например, fpath = "example.txt"
  • найдите каталог этого файла, используя ниже
  • прочитайте файл и запишите в новый файл, добавив dir_name в строку, прочитанную перед записью.

Доступ к каталогу можно сделать с помощью

import os
fpath = "example.txt"
dir_name = os.path.dirname(fpath)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...