Как я могу автоматически преобразовать все файлы исходного кода в папке (рекурсивно) в один PDF-файл с подсветкой синтаксиса?

29

Я хотел бы преобразовать исходный код нескольких проектов в один файл для печати, чтобы сэкономить на USB и распечатать позже. Как я могу это сделать?

редактировать

Прежде всего, я хочу уточнить, что я хочу печатать только не скрытые файлы и каталоги ( .gitнапример, без содержимого, например).

Чтобы получить список всех не скрытых файлов в не скрытых каталогах в текущем каталоге, вы можете выполнить find . -type f ! -regex ".*/\..*" ! -name ".*"команду в виде ответа в этой теме .

Как было предложено в той же теме, я попытался создать файл pdf из файлов с помощью команды, find . -type f ! -regex ".*/\..*" ! -name ".*" ! -empty -print0 | xargs -0 a2ps -1 --delegate no -P pdfно, к сожалению, полученный файл pdf стал полным беспорядком .

Bentley4
источник
Не знаю, подходит ли он вам, но a2ps -P file *.srcвы можете создавать файлы postscript из вашего исходного кода. Но файлы PS должны быть преобразованы и объединены впоследствии.
mpy
Используя convert ( linux.about.com/od/commands/l/blcmdl1_convert.htm , imagemagick ), вы сможете создать один pdf из ps-файлов.
ВОО
Можете ли вы прокомментировать, что вы имеете в виду под «полным беспорядком»? Это ( i.stack.imgur.com/LoRhv.png ) выглядит не так уж плохо для меня, используя a2ps -1 --delegate=0 -l 100 --line-numbers=5 -P pdf- я добавил -l100 символов в строке, чтобы избежать переноса слов и номеров строк, но это только личные предпочтения.
mpy
Для преобразования этого проекта (4 непустых не скрытых файла, каждый размером около одной страницы в не скрытых каталогах) в pdf у меня было около 5 страниц исходного кода и 39 страниц бессмысленного текста.
Bentley4

Ответы:

47

Я был заинтригован вашим вопросом и увлекся. Это решение создаст хороший PDF-файл с кликабельным индексом и выделенным цветом кодом. Он найдет все файлы в текущем каталоге и подкаталогах и создаст раздел в файле PDF для каждого из них (см. Примечания ниже, чтобы узнать, как сделать команду поиска более конкретной).

Для этого необходимо, чтобы у вас было установлено следующее (инструкции по установке предназначены для систем на основе Debian, но они должны быть доступны в репозиториях вашего дистрибутива):

  • pdflatex, colorиlistings

    sudo apt-get install texlive-latex-extra latex-xcolor texlive-latex-recommended

    Это также должно установить базовую систему LaTeX, если у вас ее нет.

Как только они будут установлены, используйте этот скрипт для создания документа LaTeX с вашим исходным кодом. Хитрость заключается в использовании пакетов listings(частично texlive-latex-recommended) и color(установленных latex-xcolor) LaTeX. Это \usepackage[..]{hyperref}то, что делает ссылки в оглавлении кликабельными ссылками.

#!/usr/bin/env bash

tex_file=$(mktemp) ## Random temp file name

cat<<EOF >$tex_file   ## Print the tex file header
\documentclass{article}
\usepackage{listings}
\usepackage[usenames,dvipsnames]{color}  %% Allow color names
\lstdefinestyle{customasm}{
  belowcaptionskip=1\baselineskip,
  xleftmargin=\parindent,
  language=C++,   %% Change this to whatever you write in
  breaklines=true, %% Wrap long lines
  basicstyle=\footnotesize\ttfamily,
  commentstyle=\itshape\color{Gray},
  stringstyle=\color{Black},
  keywordstyle=\bfseries\color{OliveGreen},
  identifierstyle=\color{blue},
  xleftmargin=-8em,
}        
\usepackage[colorlinks=true,linkcolor=blue]{hyperref} 
\begin{document}
\tableofcontents

EOF

find . -type f ! -regex ".*/\..*" ! -name ".*" ! -name "*~" ! -name 'src2pdf'|
sed 's/^\..//' |                 ## Change ./foo/bar.src to foo/bar.src

while read  i; do                ## Loop through each file
    name=${i//_/\\_}             ## escape underscores
    echo "\newpage" >> $tex_file   ## start each section on a new page
    echo "\section{$i}" >> $tex_file  ## Create a section for each filename

   ## This command will include the file in the PDF
    echo "\lstinputlisting[style=customasm]{$i}" >>$tex_file
done &&
echo "\end{document}" >> $tex_file &&
pdflatex $tex_file -output-directory . && 
pdflatex $tex_file -output-directory .  ## This needs to be run twice 
                                           ## for the TOC to be generated    

Запустите скрипт в каталоге, который содержит исходные файлы

bash src2pdf

Это создаст файл с именем all.pdfв текущем каталоге. Я попробовал это с парой случайных исходных файлов, которые я нашел в моей системе (в частности, два файла из источника vlc-2.0.0), и это скриншот первых двух страниц полученного PDF:

введите описание изображения здесь


Пара комментариев:

  • Скрипт не будет работать, если имена файлов вашего исходного кода содержат пробелы. Поскольку мы говорим об исходном коде, я предполагаю, что это не так.
  • Я добавил, ! -name "*~"чтобы избежать резервного копирования файлов.
  • Я рекомендую вам использовать более конкретную findкоманду для поиска ваших файлов, в противном случае любой случайный файл будет включен в PDF. Если все ваши файлы имеют определенные расширения ( .cи, .hнапример), вы должны заменить findв скрипте что-то вроде этого

    find . -name "*\.c" -o -name "\.h" | sed 's/^\..//' | 
  • Поэкспериментируйте с listings опциями , вы можете настроить их так, как вы хотите.
terdon
источник
1
Вау, это то, что я называю ответом! :)
mpy
1
О Боже, Тердон, тебе принадлежал этот вопрос ^^. Другим людям, пробующим скрипт: если вы столкнетесь src2pdf: line 36: warning: here-document at line 5 delimited by end-of-file (wanted EOF')при запуске скрипта, вы должны удалить пробел в строке EOF, чтобы он заработал.
Bentley4
1
Если ваш файл вызывается, src2pdfвставьте ! -name "src2pdf"в findстроку в сценарии, как это, find . -type f ! -regex ".*/\..*" ! -name "src2pdf" ! -name ".*" ! -name "*~" |чтобы пропустить его в PDF.
Bentley4
1
@ Bentley4 спасибо! Я удалил пробел (он был добавлен, когда я вставил скрипт в ответ) и добавил фильтр, чтобы удалить сам скрипт из findрезультатов (я сохранил скрипт в другом каталоге, который был в моем $ PATH, поэтому у меня его не было проблема). Кроме того, вы можете изменить язык, используемый для исходных файлов, чтобы иметь лучшую разметку, изменив language=C++на то, что вы хотите, он может работать со многими различными языками, см. Здесь .
тердон
1
@ qubodup Я действительно не знаю. LaTeX и UTF8 могут быть хитрыми. Он должен работать с \usepackage[utf8]{inputenc} \ usepackage [german] {babel} `, но в моих тестах он не работает. Тем не менее, я подозреваю, что я не кормлю это правда utf8 Это может стоить своего собственного вопроса, но я предлагаю вам спросить о TeX - LaTeX , они должны знать.
Тердон
2

(из StackOverflow )

for i in *.src; do echo "$i"; echo "---"; cat "$i"; echo ; done > result.txt

Это приведет к result.txt, содержащему:

  • Имя файла
  • разделитель (---)
  • Содержимое файла .src
  • Повторяйте сверху, пока все * .src файлы не будут сделаны

Если ваш исходный код имеет другое расширение, просто измените при необходимости. Вы также можете отредактировать бит эха, чтобы добавить необходимую информацию (может быть, эхо «имя файла $ 1» или изменить разделитель, или добавить разделитель конца файла).

У ссылки есть другие методы, поэтому используйте любой метод, который вам больше нравится. Я нахожу этот вариант наиболее гибким, хотя с небольшой кривой обучения.

Код будет отлично работать на терминале bash (только что протестирован на Ubuntu VirtualBox)

Если вас не интересует имя файла, а просто содержимое файлов, слитых вместе:

cat *.src > result.txt

будет работать отлично

Другой предложенный метод был:

grep "" *.src > result.txt

Который будет префикс каждой строки с именем файла, что может быть полезно для некоторых людей, лично я нахожу это слишком много информации, поэтому мое первое предложение - цикл for выше.

Благодарим тех, кто на форуме StackOverflow.

РЕДАКТИРОВАТЬ: Я только что понял, что в качестве конечного результата вы используете именно HTML или PDF, некоторые решения, которые я видел, это распечатать текстовый файл в PostScript, а затем преобразовать PostScript в PDF. Некоторый код, который я видел:

groff -Tps result.txt > res.ps

тогда

ps2pdf res.ps res.pdf 

(Требуется, чтобы у вас был ghostscript)

Надеюсь это поможет.

Darius
источник
Это работает только для файлов с определенным расширением (.src), но я хочу, чтобы каждый файл помещался в этот pdf независимо от расширения. Я хотел бы опустить не скрытые каталоги и не скрытые файлы, хотя. Я отредактировал оригинальное сообщение, не могли бы вы взглянуть на него?
Bentley4
2

Я знаю, что я слишком поздно, но кто-то ищет решение может найти это полезным.

Основываясь на ответе @ terdon, я создал скрипт BASH, который выполняет эту работу: https://github.com/eljuanchosf/source-code-to-pdf

eljuanchosf
источник
Пожалуйста, процитируйте основные части ответа по ссылочной ссылке (ссылкам), так как ответ может стать недействительным, если связанные страницы изменятся.
DavidPostill