使用文件夹名称作为文本文件中的一列

发布于 2025-01-08 09:22:17 字数 457 浏览 1 评论 0原文

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

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

就像文件夹 the_peasant 中的文本文件 text.txt

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 的组合,但我看不到它。有什么想法吗?

The lazy me is thinking about adding a column to some textfiles.

The textfiles are in directories and I would like to add the directory name to the text file.

Like the text file text.txt in the folder the_peasant:

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

would become:

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

Then I have similar text files in other folders called "the_king" etc.

I would think this is a combination of the find command, bash scripting and sed but I cant see it through. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

流云如水 2025-01-15 09:22:17

这可能对你有用:

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

或者如果你有 GNU sed:

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

This might work for you:

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

or if you have GNU sed:

find . -name text.txt | sed 's|.*/\(.*\)/.*|sed -i "s@^@\1 @" & |e' 
辞慾 2025-01-15 09:22:17

目录树:

% 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

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

The directory tree:

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

Directories and contents before:

% 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

Code (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

Which outputs:

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

Directories and contents after:

% 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

This was fun! Thanks for the challenge!

梦行七里 2025-01-15 09:22:17

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

Simple python script for this (should work from any folder, as long as you pass the fullpath to the target file, obviously):

#!/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()
妳是的陽光 2025-01-15 09:22:17

这是我的想法:

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

Here is what I came up with:

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

Here is an example of how the commands would be constructed, assuming the following files exist:

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

First find /home/the_peasant -type f would output those files exactly as above.

Next, the sed command would output a file name, followed by the directory name, like this:

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

The xargs would group every two lines and pass them to the sh command, so you would end up with the following three commands:

$ 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

And finally this will result in the following sed commands which will add the folder name to the beginning of each line:

$ 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
温折酒 2025-01-15 09:22:17

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

Obligatory single liner using find and 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

Assumes perl and sed are in your $PATH. Generates a file of sed commands to do the actual change so you can review what is to be done.

In my test, that command file looks like so:

sed -i "s/^/foo /" foo/text1
sed -i "s/^/foo /" foo/text2
sed -i "s/^/bar /" bar/belvedere
sed -i "s/^/bar /" bar/robin
你的背包 2025-01-15 09:22:17

我会的。

  • 获取文件路径,例如 fpath = "example.txt"
  • 使用以下命令查找该文件的目录:
  • 在文件中读取并写入一个新文件,将 dir_name 附加到写入之前刚刚读取的行。

可以使用以下方式访问该目录

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

I would.

  • get the file path e.g fpath = "example.txt"
  • find the directory of that file using the below
  • read in the file and write to a new file appending dir_name to the row just read before writing.

Accessing the directory can be done by using

import os
fpath = "example.txt"
dir_name = os.path.dirname(fpath)
猫性小仙女 2025-01-15 09:22:17

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

Are you running the script in the appropriate folder? Then you can use the os module to find the current folder. Say you wanted to take just the end of the directory tree, you could use os.path, like:

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()
朮生 2025-01-15 09:22:17

编辑:注意到有些东西不正确。
我删除了 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)

Edit: noticed something wasn't correct.
I removed the dir loop - its recursively walking now.
Sorry for the mix up.

Using 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)
始终不够爱げ你 2025-01-15 09:22:17

这是 bash 和 awk 中的 one-ish-liner:

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

Here's a one-ish-liner in bash and 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文