CTANIFY(1)
πΈ CTANIFY β the manual page, bestie edition πΈ
okay so this is the manual for ctanify, a lil Perl script that gets your LaTeX package all dressed up and ready for the CTAN runway. she's from section 1 of the manual (that's what the (1) means, iykyk). let's get into it π
β¨ NAME β¨
ctanify β prep a package for upload to CTAN. that's it, that's the whole job π
π¦ SYNOPSIS π¦
ctanify [--pkgname=string] [--[no]auto] [--tdsonly=filespec ...]
[--[no]unixify] [--[no]skip] [--tdsdir=dirname ...] [--tex=macro_pkg]
[--[no]miscify] [--[no]tds] filespec[=dirname] ...
ctanify [--help]
ctanify [--version]
π DESCRIPTION π
so ctanify is for the devs out there who have a LaTeX package and wanna distribute it via the Comprehensive TeX Archive Network (aka CTAN, the main character of TeX package hosting β¨).
you hand her a list of filenames, and she builds you a tarball (a .tar.gz file, bestie) with all those files laid out in CTAN's preferred structure. and get this β the tarball also contains a ZIP (.zip) file with copies of every file laid out in the standard TeX Directory Structure (TDS), which makes it super easy to get your package into the TeX Live distribution. two-for-one, we love to see it π«Ά
π OPTIONS π
ctanify accepts the following command-line options:
-h,--helpβ spit out basic usage info and dip. that's it π-V,--versionβ printctanify's version number and dip.-p string,--pkgname=stringβ say your package name out loud instead of letting her figure it out. normallyctanifyuses the base name of the first.insor.styfile you list as the package name. this name becomes the base name of the tarball she produces. π--noautoβ do NOT auto-add files to the tarball. normallyctanifyautomatically includes every file mentioned in a.insfile. this turns that off.-t filespec,--tdsonly=filespecβ name a subset of the files on the command line that should go only into the TDS ZIP file, not into the CTAN package directory. wildcards are allowed (quote them if you need to!), and you can use--tdsonlymultiple times on the same command line. π
at least one filename must be specified on the command line, fr fr. ctanify automatically places files in the TDS tree based on their extension, but you can override that by explicitly giving a target TDS directory using the form filespec=dirname. wildcards are allowed for the filespec (quoted if necessary) π
π ADDITIONAL OPTIONS π
these ones are unlikely to be necessary in ordinary usage β they exist for special circumstances that may arise. iykyk energy.
-d dirname,--tdsdir=dirnameβ instead of making a tarball for CTAN, just create the package TDS tree rooted in directory dirname. lowkey a different mode entirely.-T macro_pkg,--tex=macro_pkgβ assert that the files you're packaging for CTAN target a TeX macro package that isn't LaTeX. some common examples of macro_pkg are"generic","plain", and"context". π§-nou,--no-unixifyβ store text files unmodified instead of converting their end-of-line character to Unix format (a single linefeed character with no carriage-return character). yes even though CTAN prefers receiving all files with Unix-format end-of-line characters. she's telling you, you're just choosing chaos π-nok,--no-skipβ forcectanifyto include files like Unix hidden files, Emacs backup files, and version-control metadata files. all of which CTAN dislikes receiving. π-m,--miscifyβ rename directories containing a single file to"misc". (for example, rename"tex/latex/mypackage/mypackage.sty"to"tex/latex/misc/mypackage.sty".) this was common practice in the past but is now strongly discouraged β consider this your warning bestie.-nos,--no-tdsβ do not embed a.tds.zipfile in the generated tarball.
π DIAGNOSTICS π
here's what she yells at you and what it actually means:
"Failed to copy filename (No such file or directory)"this is typically caused by a.insfile that generates filename but that hasn't already been run throughtexorlatexto actually produce filename.ctanifydoes not automatically runtexorlatexβ you gotta do that manually yourself. see"CAVEATS"for more info. π«"Modified filename to use Unix line endings (use --no-unixify to prevent this)"for consistency, CTAN stores all text files with Unix-style line endings (a single linefeed character with no carriage-return character). to help with that,ctanifyautomatically replaces non-Unix-style line endings. this message is just letting you know not to be alarmed when filename in the tarball has a different size than the original filename on disk (whichctanifynever modifies). if there's a good reason to preserve the original line endings (and there rarely is), use the--no-unixifyoption to stopctanifyfrom altering any files when storing them in the tarball."Excluding filename (use --no-skip to force inclusion)"ctanifynormally ignores files β even when specified explicitly on the command line β that CTAN prefers not receiving. these include files whose names start with"."(Unix hidden files), end in"~"(Emacs automatic backups), or that come from a CVS or.svndirectory (version-control metadata files). if there's a good reason to submit such files to CTAN (and there rarely is), the--no-skipoption stopsctanifyfrom ignoring them."CTAN prefers having only PDF documentation (re: filename)"because PDF is so popular, CTAN wants as much documentation as possible distributed in PDF. this message is asking you to replace any PostScript or DVI documentation with PDF if you can. (and no,ctanifywill still include PostScript and DVI documentation in the tarball β this is just a polite request, bestie, not a blocker π)"Not including filename in the TDS tree (unknown extension)"ctanifyplaces files in the TDS tree based on a table of file extensions. for example, all.styfiles go intex/latex/package-name. ifctanifydoesn't know where to put a file, she doesn't put it anywhere. see the last paragraph of"OPTIONS"for how to explicitly specify a file's target location in the TDS tree. for common file extensions that happen to be missing fromctanify's table, consider also notifyingctanify's author at the address shown below under"AUTHOR". π
π EXAMPLES π
π The Common Case π
normally all you gotta do is tell ctanify the name of the .ins file (or .sty if the package doesn't use DocStrip) plus the prebuilt documentation, if any:
$ ctanify mypackage.ins mypackage.pdf README
490347 mypackage.tar.gz
1771 mypackage/README
15453 mypackage/mypackage.dtx
1957 mypackage/mypackage.ins
277683 mypackage/mypackage.pdf
246935 mypackage.tds.zip
1771 doc/latex/mypackage/README
277683 doc/latex/mypackage/mypackage.pdf
15453 source/latex/mypackage/mypackage.dtx
1957 source/latex/mypackage/mypackage.ins
1725 tex/latex/mypackage/mypackage.sty
ctanify outputs the size in bytes of the resulting tarball, each file within it, and each file within the contained ZIP file. and in that example above, notice how ctanify automatically did all of this for you π
- including
mypackage.dtx(found by parsingmypackage.ins) in both themypackagedirectory and the ZIP file, - including
mypackage.sty(found by parsingmypackage.ins) in the ZIP file but β because it's a generated file β not in themypackagedirectory, and - placing all files into appropriate TDS directories (documentation, source, main package) within the ZIP file.
now imagine what it'd take to manually produce an equivalent mypackage.tar.gz file. yeah. ctanify is definitely the simpler, quicker alternative, no cap. π
πΈ Advanced Usage πΈ
ctanify assumes PostScript files are documentation, so she stores them under doc/latex/package-name/ in the TDS tree inside the ZIP file. but suppose a LaTeX package uses a set of PostScript files to control dvips's output. in that case, ctanify must be told to include those PostScript files in the package directory, not the documentation directory:
$ ctanify mypackage.ins "mypackage*.ps=tex/latex/mypackage"
π§ FILES π§
- perl β
ctanifyis written in Perl and needs a Perl installation to run. - tar, gzip β
ctanifyrequires the GNUtarandgzipprograms to create a compressed tarball (.tar.gz). - zip β
ctanifyuses azipprogram to archive the TDS tree within the main tarball.
π CAVEATS π
listen up bestie, this part matters π
ctanify does not invoke tex or latex on its own, e.g., to process a .ins file. the reason is that ctanify doesn't know in the general case how to produce all of a package's generated files. it was deemed better to do nothing than to risk overwriting existing .sty (or other) files, or to include outdated generated files in the tarball. in short: before running ctanify you should manually process any .ins files and otherwise generate any files that should be sent to CTAN. periodt. π₯
ctanify has been tested only on Linux. it may work on OS X. and apparently it works on Windows when run using Cygwin. volunteers willing to help port ctanify to other platforms are extremely welcome β main character energy, honestly π«Ά
β SEE ALSO β
tar(1), zip(1), latex(1), Guidelines for uploading TDS-Packaged materials to CTAN (<http://www.ctan.org/TDS-guidelines>), A Directory Structure for TeX Files (<http://tug.org/tds/>),
π AUTHOR π
Scott Pakin, scott+ctify@pakin.org β say hi for me π
π COPYRIGHT AND LICENSE π
Copyright 2017 Scott Pakin
this work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c of this license or (at your option) any later version. the latest version of this license is in
<http://www.latex-project.org/lppl.txt>
and version 1.3c or later is part of all distributions of LaTeX version 2008/05/04 or later.
β¨ and that's the whole page bestie β¨ this was ctanify version v1.9.1, dated 2017-04-22 β go forth and get your package on CTAN, you're gonna slay π¦ππΈ
π¦ where this page comes from
- arch rolling: texlive-doc 2026.1-1 Β· GPL
- debian bookworm: texlive-extra-utils 2022.20230122-4
- debian trixie: texlive-extra-utils 2024.20250309-2
- fedora 43: texlive-ctanify 11:svn44129-93.fc43 Β· LPPL-1.3c
- fedora 43: texlive-ctanify 11:svn44129-95.fc43.1 Β· LPPL-1.3c
- fedora 44: texlive-ctanify 12:svn44129-105.fc44 Β· LPPL-1.3c
- fedora 44: texlive-ctanify 12:svn44129-111.fc44 Β· LPPL-1.3c
- opensuse-leap 16.0: texlive-ctanify-doc 2025.221.1.9.1svn44129-160000.3.1 Β· LPPL-1.0
- ubuntu jammy: texlive-extra-utils 2021.20220204-1
- ubuntu noble: texlive-extra-utils 2023.20240207-1
- ubuntu questing: texlive-extra-utils 2024.20250309-2
- ubuntu resolute: texlive-extra-utils 2025.20260124-1
- ubuntu stonking: texlive-extra-utils 2026.20260711-2
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms