2012-02-22 10 views
5

Tôi lười biếng đang nghĩ đến việc thêm cột vào một số tệp văn bản.Sử dụng tên thư mục làm cột trong một tệp văn bản

Các tệp văn bản nằm trong các thư mục và tôi muốn thêm tên thư mục vào tệp văn bản.

Giống như các tập tin văn bản text.txt trong thư mục the_peasant:

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

sẽ trở thành:

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

Sau đó, tôi có tập tin văn bản tương tự như trong các thư mục khác gọi là "the_king" vv

Tôi nghĩ rằng đây là một sự kết hợp của lệnh find, bash scripting và sed nhưng tôi không thể nhìn thấy nó thông qua. Bất kỳ ý tưởng?

+2

Các lười biếng tôi là đề nghị bạn đăng một số mã để chỉ ra rằng bạn đã ít nhất làm một số công việc về điều này. –

Trả lời

1

Cây thư mục:

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

Thư mục và nội dung trước:

% 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 

Mã (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 

Những kết quả đầu ra:

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 

Thư mục và nội dung sau:

% 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 

Đây là thú vị! Cảm ơn bạn đã thử thách!

+0

Cảm ơn, tôi đã sử dụng nó với những thay đổi nhỏ. Tôi đã hy vọng học hỏi từ một kịch bản bash hoặc per/sed/awk một lót nhưng điều này là quá hấp dẫn. – AWE

+0

Tuyệt vời Tôi rất vui vì bạn thấy nó hữu ích! :) Một lớp lót có vị trí của chúng, nhưng kịch bản là mãi mãi. – jathanism

0

Tôi muốn.

  • nhận được đường dẫn tập tin ví dụ fpath = "example.txt"
  • tìm thư mục của tập tin đó bằng cách sử dụng dưới đây
  • đọc trong tập tin và ghi vào một tập tin mới phụ dir_name vào hàng chỉ đọc trước khi viết.

Truy cập vào thư mục có thể được thực hiện bằng cách sử dụng

import os 
fpath = "example.txt" 
dir_name = os.path.dirname(fpath) 
0

Bạn đang chạy script trong thư mục thích hợp? Sau đó, bạn có thể sử dụng mô-đun os để tìm thư mục hiện tại. Giả sử bạn muốn lấy chỉ cuối của cây thư mục, bạn có thể sử dụng os.path, như:

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() 
1

script python đơn giản cho điều này (nên làm việc từ bất kỳ thư mục, miễn là bạn vượt qua fullpath đến nhắm mục tiêu tập tin, rõ ràng):

#!/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

Giả sử các tệp của bạn đủ nhỏ để được lưu giữ hoàn toàn trong bộ nhớ –

1

Dưới đây là những gì tôi đã đưa ra:

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

Dưới đây là một ví dụ về cách các lệnh sẽ được xây dựng, giả sử các tập tin sau đây tồn tại:

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

Đầu tiên find /home/the_peasant -type f sẽ xuất các tệp đó chính xác như trên.

Tiếp theo, lệnh sed sẽ ra một tên tập tin, theo sau là tên thư mục, như thế này:

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

Các xargs sẽ nhóm mỗi hai dòng và vượt qua chúng để lệnh sh, vì vậy bạn sẽ kết thúc lên với ba lệnh sau:

$ 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 

Và cuối cùng này sẽ dẫn đến các lệnh sed sau đó sẽ thêm tên thư mục vào đầu mỗi dòng:

$ 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 
0

Chỉnh sửa: nhận thấy có điều gì đó không chính xác. Tôi đã xóa vòng lặp dir - bước đi đệ quy của nó ngay bây giờ. Xin lỗi vì sự kết hợp.

Sử dụng 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() 

Output:

list1.py # LAB(replace solution) 
list1.py # return 
list1.py # LAB(end solution) 
1

buộc đơn lót sử dụng tìm và 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 

Giả perl và sed là trong $ PATH của bạn. Tạo ra một tập tin các lệnh sed để thực hiện thay đổi thực tế để bạn có thể xem lại những gì sẽ được thực hiện.

Trong thử nghiệm của tôi, rằng tập lệnh trông giống như vậy:

sed -i "s/^/foo /" foo/text1 
sed -i "s/^/foo /" foo/text2 
sed -i "s/^/bar /" bar/belvedere 
sed -i "s/^/bar /" bar/robin 
+0

Bạn nhận được +1 cho một lớp lót đó, bởi vì ...Vâng, yeah – jathanism

+1

Vâng, tôi nghĩ rằng một lớp lót và perl đều chưa được trình bày, vì vậy tôi đã quyết định giết hai con chim bằng một viên đá. – kbenson

0

Dưới đây là một one-ish-liner trong bash và 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 
3

Điều này có thể làm việc cho bạn:

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

hoặc nếu bạn có GNU sed:

find . -name text.txt | sed 's|.*/\(.*\)/.*|sed -i "[email protected]^@\1 @" & |e' 
+0

Đ BEP !!!! (cú pháp xấu xí, nhưng vẫn tuyệt vời) – AWE

+0

Bây giờ đó là một lớp lót ngọt ngào. – jathanism