【问题标题】:Insert file names into files using find and sed使用 find 和 sed 将文件名插入文件
【发布时间】:2015-05-06 13:34:28
【问题描述】:

我有数百个 .htm 文件,我需要将 <title>sometext</title> 替换为实际文件名。 例如: 我有一个名为records-england.htm 的文件,我需要将这个文件中的<title>sometext</title> 替换为类似<title>records-england.htm</title> 的文件名

如果没有扩展,那就更好了——但这并不重要。 我试过这样但它不起作用:

find . -name *.htm | while read file; do sed "s|<title>sometext</title>|<title>$file</title>|g" {} \; done

有什么建议吗?

【问题讨论】:

  • 标题总是sometext 还是一些随意的文字?
  • while read filedo sed ... 是两个独立的子进程。 $file 变量在第二个中不存在。
  • @legends2k,总是相同的文字
  • 你有gnu awk 4.1 并且可以测试我的解决方案吗?
  • 我有使用 Ubuntu 14.04 的 gnu awk 4.0.1,但它不工作

标签: linux bash sed find


【解决方案1】:

这适用于任意标题文本。如果您不希望它是任何文本,而是一些固定文本,请将 &lt;title&gt;.*&lt;/title&gt; 更改为 &lt;title&gt;sometext&lt;/title&gt;

 find -type f -name '*.htm' -printf '%P\0%f\0' | xargs -0 -n2 sh -c 'fil="${2/\.htm/}"; sed -i -e "s;<title>.*</title>;<title>$fil</title>;" $1' replace

它使用xargsfind 的结果传输到shbash 剥离扩展名并将参数提供给 sed 进行替换。

参数:

find

  • -type f查找文件
  • -name '*.htm' 扩展名为 htm
  • printf '%P\0%f\0' 输出完整文件路径,然后是 ASCII 空值,然后是文件名(剥离路径),然后是 ASCII 空值

xargs

  • -0 使用 ASCII nul 作为分隔符
  • -n2 每次执行命令时最多从列表中选择 2 个参数

sh

  • -c 从第一个非选项参数中读取命令
  • 一个以$1(文件路径)和$2(文件名)为参数的bash脚本;进行正则表达式替换以剪断扩展名。传递一个虚拟字符串 replace 以获取 $0

sed

  • -i 在文件中就地替换
  • -e要执行的脚本

【讨论】:

  • 它可以工作,但我有很多子文件夹,并且还会将子文件夹名称添加到 + 文件扩展名中。是否可以将文件名添加到 <title> 没有子文件夹名称和没有扩展名?
  • 假设文件名中没有元字符,;'。为了安全起见,您需要在之前准备一点文件名(变量内容)。使用相同的 sed,但首先使用此预防措施包含在批次中。
  • 对不起,它在子文件夹中不起作用。 sed:无法读取 04.06.2000-basel.htm:没有这样的文件或目录 确切的 htm 文件在子文件夹中。
  • 不适合我:sed: can't read results/2010/18.07.2010: No such file or directory sed: can't read -: No such file or directory sed: can't read gavle.htm: No such file or directory. 路径和文件名是:results/2010/18.07.2010-gavle.htm
  • @Jaur 现在检查固定答案,替换标题时它也会删除扩展名。
【解决方案2】:

你也可以试试这个:

#!/bin/bash
outFile=/tmp/myOutFile.out
touch $outFile
while read line
do
    name=$line
    echo "<title>$name</title>" >> $outFile
done < $1
  1. 使用上面的代码创建一个新的 .sh(例如 modifyFile.sh)文件。
  2. 授予它执行权限 - chmod +x modifyFile.sh
  3. 使用包含您的文件名的文件或 w/e - ./modifyFile.sh myInputFile.txt 运行它
  4. 您将在 /tmp/myOutFile.out 中获得结果

【讨论】:

    【解决方案3】:

    您可以使用awks 文件名。由于-i inplace,需要gnu awk >= 4.1

    awk -i inplace '{a=FILENAME;sub(/\.htm$/,"",a);gsub(/<title>[^<]*<\/title>/,"<title>"a"</title>")}1' *.htm
    

    这会将&lt;title&gt;sometext&lt;/title&gt;sometext 可以是任何东西)更改为&lt;title&gt;filename(without extension)&lt;/title&gt;

    【讨论】:

    • 它没有转到子文件夹,但我将所有 .htm 文件移动到当前文件夹,您的命令运行良好。谢谢。
    • 我试图让它与子文件夹一起工作,它像这样分叉:find -name "*.htm" -print -exec awk -i inplace '{a=FILENAME;sub(/\ .htm$/,"",a);gsub(/[^/,"<title>"a"")}1' {} \;是否可以删除路径?在某处使用 -F/ 之类的?文件中的实际结果:./results/2014/19.10.2014 - pila 文件中的预期结果:19.10.2014 - pila
    【解决方案4】:

    要解决代码中的问题,您可以试试这个:

    find -name "*.htm" | while read file; do sed "s|<title>sometext</title>|<title>${file##*/}</title>|g" -i $file; done
    

    Sed 需要 -i 选项来指定要编辑的文件,我使用参数扩展来仅显示文件的基本名称。

    【讨论】:

    • option g 在这种情况下不需要(除非 html 文件格式错误)。假设标题不带有元字符。为此,您可以在前面的指令中准备一个 转义 版本的文件名,以便在 sed 中使用。
    【解决方案5】:

    这样试试

    's/\<title\>.*\<title\>/title>$file<title/g'
    

    【讨论】:

      猜你喜欢
      • 2011-12-10
      • 2016-08-27
      • 2011-06-15
      • 1970-01-01
      • 1970-01-01
      • 2019-03-02
      • 2012-06-29
      • 2018-10-20
      相关资源
      最近更新 更多