【问题标题】:Convert all files of a specified extension within a directory to pdf, recursively for all sub-directories将目录中指定扩展名的所有文件转换为pdf,递归地用于所有子目录
【发布时间】:2019-02-11 23:37:35
【问题描述】:

我正在使用以下代码(来自this answer)将当前目录中的所有 CPP 文件转换为名为 code.pdf 的文件,并且效果很好:

find . -name "*.cpp" -print0 | xargs -0 enscript -Ecpp -MLetter -fCourier8 -o - | ps2pdf - code.pdf

我想改进这个脚本:

  1. 使其成为一个 .sh 文件,该文件可以接受一个参数来指定 扩展而不是将其硬编码为 CPP;

  2. 让它递归运行,访问当前目录的所有子目录;

  3. 对于遇到的每个子目录,将具有指定扩展名的所有文件转换为名为 $NameOfDirectory$.PDF 并放置在该子目录中的单个 PDF;

    李>

【问题讨论】:

  • find 将检索以扩展名结尾的所有子目录中的所有文件(在您的示例中为cpp)。如果这是您想要的,那么您的递归子弹没有意义。我想要当前目录中的所有文件,没有理由使用 find。
  • 我使用的行是我工作的基础,取自 StackOverflow 上的另一个答案(见链接)。我的要点是我想要添加的改进。

标签: linux bash find xargs enscript


【解决方案1】:

首先,如果我理解正确的话,这个要求:

对于遇到的每个子目录,将指定扩展名的所有文件转换为名为 $NameOfDirectory$.PDF 的单个 PDF

是不明智的。如果这意味着,比如说,a/b/c/*.cpp 被写入./c.pdf,那么如果你还有a/d/x/c/*.cpp,你就完蛋了,因为两个目录的内容都映射到同一个 PDF。这也意味着*.cpp(即当前目录中的CPP文件)被写入一个名为./..pdf的文件。

这样的东西,它根据所需的扩展名命名 PDF 并将其放在每个子目录中与其源文件一起,没有这些问题:

#!/usr/bin/env bash
# USAGE: ext2pdf [<ext> [<root_dir>]]
# DEFAULTS: <ext> = cpp
#           <root_dir> = .
ext="${1:-cpp}"
rootdir="${2:-.}"

shopt -s nullglob

find "$rootdir" -type d | while read d; do

  # With "nullglob", this loop only runs if any $d/*.$ext files exist
  for f in "$d"/*.${ext}; do

    out="$d/$ext".pdf
    # NOTE: Uncomment the following line instead if you want to risk name collisions
    #out="${rootdir}/$(basename "$d")".pdf

    enscript -Ecpp -MLetter -fCourier8 -o - "$d"/*.${ext} | ps2pdf - "$out"

    break   # We only want this to run once

  done

done

【讨论】:

  • 是的,我忘了指定我想要源文件旁边的 PDF,所以每个包含 CPP 文件的目录都有一个 PDF。我正在测试你的方法,并会发表评论。
  • 它不起作用。我 printf-debugged 似乎要遍历所有目录,但是 for 循环不起作用(for f in "$d"/*.${e}; do)。我很肯定这些子目录中有 CPP 文件。
  • @binarez 哎呀,对不起。为了清楚起见,我将$e 重命名为$ext,但并没有更改每个实例。现已修复。
【解决方案2】:

首先,如果我理解正确,您使用的实际上是错误的 - find 将从所有子目录中检索文件。递归工作,只从当前目录获取文件(我将其命名为do.bash):

#!/bin/bash

ext=$1
if ls *.$ext &> /dev/null; then
    enscript -Ecpp -MLetter -fCourier8 -o - *.$ext | ps2pdf - $(basename $(pwd)).pdf
fi
for subdir in */; do
    if [ "$subdir" == "*/" ]; then break; fi
    cd $subdir
    /path/to/do.bash $ext
    cd ../
done

检查是为了确保具有扩展名的文件或子目录确实存在。此脚本在当前目录上运行,并递归调用自身 - 如果您不想要完整路径,请将其放在 PATH 列表中,尽管完整路径很好。

【讨论】:

  • 感谢您的回答,但为了简单起见,我将采用不需要脚本位于用户路径中的解决方案。
猜你喜欢
  • 2011-06-27
  • 1970-01-01
  • 2021-09-18
  • 2021-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多