对于所有子目录,将目录中指定扩展名的所有文件递归转换为pdf

时间:2019-02-11 13:49:24

标签: linux bash find xargs enscript

我正在使用以下代码(来自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,并放置在该子目录中;

2 个答案:

答案 0 :(得分:1)

首先,如果我理解正确,那么您使用的实际上是错误的-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列表中。

答案 1 :(得分:1)

首先,如果我理解正确,则此要求:

  

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

是不明智的。如果这意味着a/b/c/*.cpp被刻写为./c.pdf,那么如果您也拥有a/d/x/c/*.cpp,您将一头雾水,因为两个目录的内容都映射到相同的PDF。这也意味着*.cpp(即 current 目录中的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