繁体   English   中英

将文件夹名称用作文本文件中的列

[英]Use the folder name as a column in a text file

懒惰的我正考虑在一些文本文件中添加一列。

文本文件位于目录中,我想将目录名添加到文本文件中。

像文件夹the_peasant的文本文件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的组合,但我无法看透。 有任何想法吗?

这可能对你有用:

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

或者如果你有GNU sed:

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

这个简单的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()

这是我想出的:

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

使用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

目录树:

% 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

这很有趣! 感谢您的挑战!

我会。

  • 获取文件路径,例如fpath =“example.txt”
  • 使用下面的代码找到该文件的目录
  • 读入文件并写入一个新文件,将dir_name附加到刚写入之前读取的行。

访问目录可以使用

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

您是否在相应的文件夹中运行脚本? 然后,您可以使用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()

编辑:发现有些事情不正确。 我删除了dir循环 - 它现在递归行走。 抱歉混淆了。

使用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)

这是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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM