<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Command Line on KnightLi Blog</title>
        <link>https://knightli.com/en/tags/command-line/</link>
        <description>Recent content in Command Line on KnightLi Blog</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Mon, 25 May 2026 00:24:36 +0800</lastBuildDate><atom:link href="https://knightli.com/en/tags/command-line/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>CLI-Anything: Turning Software into an Agent-Usable Command Line</title>
        <link>https://knightli.com/en/2026/05/25/cli-anything-agent-native-cli/</link>
        <pubDate>Mon, 25 May 2026 00:24:36 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/25/cli-anything-agent-native-cli/</guid>
        <description>&lt;p&gt;CLI-Anything is an open-source Agent tooling project from HKUDS. Its goal is to turn software that was originally designed for human GUI operation into command-line interfaces that AI Agents can call more easily. It does not reimplement a simplified version of the software. Instead, it builds a CLI harness around the existing codebase and real backend, allowing Agents to complete tasks through stable commands, stateful sessions, and structured output.&lt;/p&gt;
&lt;p&gt;This direction addresses one of the most common gaps when Agents use software: GUI automation depends on screenshots, clicks, and coordinates, so it is easily affected by interface changes; a single API is also often incomplete, forcing the Agent to stitch together a large amount of context on its own. CLI-Anything chooses to condense software capabilities into a command line because commands are naturally easier for models to read, combine, and verify, while also fitting neatly into scripts and automation workflows.&lt;/p&gt;
&lt;h2 id=&#34;how-it-works&#34;&gt;How it works
&lt;/h2&gt;&lt;p&gt;The official repository describes CLI-Anything as a pipeline for automatically generating CLIs. After receiving a local software source path or a GitHub repository URL, the process analyzes the code structure, identifies the backend and data models, designs command groups, and then implements the CLI, tests, and documentation.&lt;/p&gt;
&lt;p&gt;The generated CLI usually supports two usage modes. One is a REPL for continuous work, which preserves project state. The other is a subcommand mode, which is better suited to scripts and pipelines. Commands also provide JSON output so Agents can parse results directly, while still keeping a human-readable format for debugging.&lt;/p&gt;
&lt;p&gt;In the official example, the Claude Code plugin can be used like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/plugin marketplace add HKUDS/CLI-Anything
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/plugin install cli-anything
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/cli-anything &amp;lt;software-path-or-repo&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If a harness has already been generated for a piece of software, later usage is closer to a normal Python CLI:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cd &amp;lt;software&amp;gt;/agent-harness
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install -e .
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cli-anything-&amp;lt;software&amp;gt; --help
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cli-anything-&amp;lt;software&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cli-anything-&amp;lt;software&amp;gt; --json &amp;lt;command&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;where-it-fits&#34;&gt;Where it fits
&lt;/h2&gt;&lt;p&gt;CLI-Anything is especially suitable for scenarios where &amp;ldquo;the capability exists in real software, but the Agent cannot operate it reliably.&amp;rdquo; Examples include image, video, audio, office documents, 3D modeling, data analysis, or AI/ML toolchains. As long as the project has an analyzable codebase, a callable backend, or a clear data model, it has a chance to be wrapped as a command set that Agents can use.&lt;/p&gt;
&lt;p&gt;Its value is not merely adding another layer of wrapping in the command line. The real value is turning key software operations into discoverable, composable, and testable interfaces. An Agent can first understand capabilities through &lt;code&gt;--help&lt;/code&gt;, then receive results through JSON output, and connect multiple commands into a workflow. For tasks that require batch processing, automatic validation, and continuous iteration, this is more controllable than temporarily asking an Agent to click through an interface.&lt;/p&gt;
&lt;h2 id=&#34;boundaries-to-keep-in-mind&#34;&gt;Boundaries to keep in mind
&lt;/h2&gt;&lt;p&gt;CLI-Anything does not mean that any software can be integrated instantly at no cost. It depends on the target software&amp;rsquo;s source code, backend capabilities, file formats, and testability. If a piece of software is highly closed and its key logic exists only in the GUI layer, the difficulty of generating a high-quality CLI rises significantly.&lt;/p&gt;
&lt;p&gt;The official methodology also emphasizes real backends and test validation. This means generating a harness is not finished after writing a few command wrapper scripts. To use it for serious work, you still need to confirm command coverage, output format, dependency installation, real software invocation, and end-to-end test reliability. A more realistic approach is to first generate a CLI for a clearly defined workflow, then gradually fill in capabilities through commands such as refine, test, and validate.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;CLI-Anything&amp;rsquo;s idea is direct: instead of making Agents adapt to fragile human interfaces, add a stable, structured, and testable command-line entry point to existing software. It is suitable for people who want to bring professional software into Agent workflows, and also for developers studying the shape of &amp;ldquo;Agent-native software.&amp;rdquo; In real adoption, the key question is not how much code one command can generate, but whether the generated CLI can call real capabilities, preserve state, output structured results, and stand up to testing.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Ghostty Docs Quick Read: Installation, Configuration, and Daily Usage Notes</title>
        <link>https://knightli.com/en/2026/05/15/ghostty-docs-install-config-usage-guide/</link>
        <pubDate>Fri, 15 May 2026 14:50:11 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/15/ghostty-docs-install-config-usage-guide/</guid>
        <description>&lt;p&gt;Ghostty is a new terminal emulator, but it is not simply &amp;ldquo;another faster terminal.&amp;rdquo; According to its official documentation, it tries to balance three goals at the same time: speed, features, and a native desktop experience. In other words, it wants GPU acceleration and solid rendering performance, while also feeling like a real local app on macOS and Linux instead of pushing every interaction into a custom-drawn interface.&lt;/p&gt;
&lt;p&gt;If you currently use iTerm2, Kitty, Alacritty, WezTerm, or the system terminal, the most interesting part of Ghostty is not one isolated feature. It is the way it combines &amp;ldquo;works out of the box&amp;rdquo; with &amp;ldquo;deeply configurable.&amp;rdquo; The default configuration is already usable, but when you want to tune it further, the docs provide complete entry points for configuration files, themes, keybindings, fonts, Shell integration, and terminal control sequences.&lt;/p&gt;
&lt;h2 id=&#34;start-with-the-positioning&#34;&gt;Start with the Positioning
&lt;/h2&gt;&lt;p&gt;Ghostty&amp;rsquo;s core positioning can be summarized in three points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is a cross-platform terminal emulator, currently focused on macOS and Linux.&lt;/li&gt;
&lt;li&gt;It uses platform-native UI: Swift, AppKit, and SwiftUI on macOS; Zig and GTK4 on Linux.&lt;/li&gt;
&lt;li&gt;Its terminal core is &lt;code&gt;libghostty&lt;/code&gt;, and the GUI applications are built around this shared core.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This design affects daily use. Tabs, splits, error prompts, window state restoration, system shortcuts, and similar features are not merely components that &amp;ldquo;look like a desktop app.&amp;rdquo; They try to follow the interaction conventions of each operating system. The default shortcuts on macOS and Linux also differ according to platform expectations.&lt;/p&gt;
&lt;h2 id=&#34;installation-direct-on-macos-distribution-dependent-on-linux&#34;&gt;Installation: Direct on macOS, Distribution-Dependent on Linux
&lt;/h2&gt;&lt;p&gt;The official prebuilt binaries mainly target macOS. The most common installation path is to download the &lt;code&gt;.dmg&lt;/code&gt;, open it, and drag Ghostty into the Applications folder. Homebrew users can also use the community-maintained cask:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew install --cask ghostty
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Linux is more fragmented. The Ghostty docs separate package managers, community binaries, and source builds for different distributions. Arch, Alpine, Gentoo, NixOS, Snap, Solus, Void, and others all have their own paths. If a distribution has no official or trusted repository, the docs lean toward building from source rather than casually installing third-party binaries.&lt;/p&gt;
&lt;p&gt;This matters especially on servers and workstations: a terminal emulator handles a large amount of input and output, clipboard data, links, SSH sessions, and local file paths. It is better to be conservative with the installation source, preferring the official macOS package, distribution repositories, or a build process whose source you can audit.&lt;/p&gt;
&lt;h2 id=&#34;configuration-do-not-rush-to-copy-a-giant-dotfiles-setup&#34;&gt;Configuration: Do Not Rush to Copy a Giant dotfiles Setup
&lt;/h2&gt;&lt;p&gt;Ghostty&amp;rsquo;s configuration philosophy is &amp;ldquo;usable with zero configuration.&amp;rdquo; The default font includes JetBrains Mono and Nerd Font support, so most users can work normally the first time they open it. The docs even suggest that if you must configure a non-subjective option to feel comfortable, it may be worth asking whether that behavior should become the default.&lt;/p&gt;
&lt;p&gt;When you do need customization, Ghostty uses a text configuration file. The current configuration file name is &lt;code&gt;config.ghostty&lt;/code&gt;, while older versions also support &lt;code&gt;config&lt;/code&gt;. Common paths include:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$XDG_CONFIG_HOME/ghostty/config.ghostty
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$XDG_CONFIG_HOME/ghostty/config
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$HOME/.config/ghostty/config.ghostty
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$HOME/.config/ghostty/config
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;On macOS, Ghostty also reads:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$HOME/Library/Application Support/com.mitchellh.ghostty/config.ghostty
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$HOME/Library/Application Support/com.mitchellh.ghostty/config
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The syntax is straightforward: &lt;code&gt;key = value&lt;/code&gt;. For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;font-family = JetBrains Mono
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;font-size = 14
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;theme = light:Rose Pine Dawn,dark:Rose Pine
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;keybind = ctrl+shift+t=new_tab
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;A practical suggestion: do not start by copying someone else&amp;rsquo;s full configuration. A steadier approach is to run it bare for a few days and change only three things at first: font family, font size, and theme. Once you actually feel friction around shortcuts, splits, windows, or Shell integration, add those settings one by one.&lt;/p&gt;
&lt;h2 id=&#34;documentation-lookup-full-configuration-reference-is-available-locally&#34;&gt;Documentation Lookup: Full Configuration Reference Is Available Locally
&lt;/h2&gt;&lt;p&gt;Ghostty has many configuration options, and the official docs collect them in the Option Reference. Besides the web page, you can query the reference locally after installation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghostty +show-config --default --docs
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This command prints the default configuration and documentation to standard output, which is useful when piped into a pager:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghostty +show-config --default --docs &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; less
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;To list available fonts:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghostty +list-fonts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;To list built-in and available themes:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghostty +list-themes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;To view default keybindings:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghostty +list-keybinds --default
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;These commands are more reliable than copying snippets from the web, because they come from the Ghostty version installed on your own machine.&lt;/p&gt;
&lt;h2 id=&#34;keybindings-treat-actions-as-the-core-concept&#34;&gt;Keybindings: Treat &amp;ldquo;Actions&amp;rdquo; as the Core Concept
&lt;/h2&gt;&lt;p&gt;Ghostty&amp;rsquo;s keybinding format is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;keybind = trigger=action
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;trigger&lt;/code&gt; is the key sequence, and &lt;code&gt;action&lt;/code&gt; is the operation Ghostty performs. Creating a new tab, closing the current surface, reloading configuration, and jumping to a prompt are all actions. The model is clear: you are not &amp;ldquo;changing a menu item&amp;rdquo;; you are binding an input sequence to an action.&lt;/p&gt;
&lt;p&gt;After changing configuration, you can reload it at runtime. The default shortcut is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linux: &lt;code&gt;ctrl+shift+,&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;macOS: &lt;code&gt;cmd+shift+,&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not every setting takes effect immediately. Some options only affect newly created terminals, while others require a full restart. If &amp;ldquo;the config is written but nothing changed,&amp;rdquo; check the documentation for that option before spending too much time suspecting syntax.&lt;/p&gt;
&lt;h2 id=&#34;themes-and-fonts-use-built-ins-first-then-tune&#34;&gt;Themes and Fonts: Use Built-Ins First, Then Tune
&lt;/h2&gt;&lt;p&gt;Ghostty ships with many themes and supports switching themes according to the system light or dark mode:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;theme = light:Rose Pine Dawn,dark:Rose Pine
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Themes can also come from custom files. The docs are clear here: a theme file is essentially a Ghostty configuration file and can set many options, so do not casually use themes from untrusted sources.&lt;/p&gt;
&lt;p&gt;For fonts, &lt;code&gt;font-family&lt;/code&gt; can be repeated to specify fallback fonts. This is useful in multilingual environments: the primary font can handle English and symbols, while later fonts cover Chinese, Japanese, or other characters. When you encounter display details such as emoji, bold, italic, or ligatures, look up the corresponding options in the Option Reference.&lt;/p&gt;
&lt;h2 id=&#34;shell-integration-especially-important-for-ssh-users&#34;&gt;Shell Integration: Especially Important for SSH Users
&lt;/h2&gt;&lt;p&gt;Ghostty supports automatic Shell integration injection for &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;elvish&lt;/code&gt;, &lt;code&gt;fish&lt;/code&gt;, &lt;code&gt;nushell&lt;/code&gt;, and &lt;code&gt;zsh&lt;/code&gt;. When enabled, several interactions become more natural:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New terminals can open in the previous terminal&amp;rsquo;s working directory.&lt;/li&gt;
&lt;li&gt;Complex prompts can redraw correctly after resize instead of reflowing badly.&lt;/li&gt;
&lt;li&gt;You can jump between command outputs using prompt markers.&lt;/li&gt;
&lt;li&gt;Cursor behavior at the prompt can better match editing habits.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you do not want automatic injection, disable it in the configuration:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;shell-integration = none
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;SSH deserves extra attention. Ghostty uses &lt;code&gt;xterm-ghostty&lt;/code&gt; as &lt;code&gt;TERM&lt;/code&gt;, but many remote hosts do not yet have the corresponding terminfo. The docs provide two Shell integration features, &lt;code&gt;ssh-env&lt;/code&gt; and &lt;code&gt;ssh-terminfo&lt;/code&gt;, which are disabled by default and can be enabled as needed:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;shell-integration-features = ssh-env,ssh-terminfo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you often connect to old servers, containers, bastion hosts, or tightly managed production environments, read the official Terminfo and Shell Integration docs before enabling these features. Terminal capability negotiation looks minor, but when it goes wrong, the symptoms can be strange colors, broken shortcuts, or garbled full-screen programs.&lt;/p&gt;
&lt;h2 id=&#34;my-suggested-onboarding-order&#34;&gt;My Suggested Onboarding Order
&lt;/h2&gt;&lt;p&gt;If you only want to judge whether Ghostty fits you, try this sequence:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install it and use it for a day without writing any configuration.&lt;/li&gt;
&lt;li&gt;Adjust only &lt;code&gt;font-family&lt;/code&gt;, &lt;code&gt;font-size&lt;/code&gt;, and &lt;code&gt;theme&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;ghostty +list-keybinds --default&lt;/code&gt; to inspect default shortcuts instead of importing someone else&amp;rsquo;s shortcut table first.&lt;/li&gt;
&lt;li&gt;If you use SSH often, check remote host terminfo compatibility early.&lt;/li&gt;
&lt;li&gt;Finally, tune splits, windows, transparency, title bar, background image, and other visual or workflow preferences.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ghostty&amp;rsquo;s docs are engineering-oriented. They are better read as a configuration reference manual than as a marketing page. For most users, the real evaluation criteria are simple: does the default experience already feel comfortable, and are your daily editor, Shell, SSH, tmux, or Zellij workflows stable? If those pieces work well, Ghostty deserves a place on your long-term terminal shortlist.&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ghostty.org/docs&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Ghostty Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ghostty.org/docs/about&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;About Ghostty&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ghostty.org/docs/config&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ghostty.org/docs/config/keybind&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Custom Keybindings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ghostty.org/docs/install/binary&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Prebuilt Ghostty Binaries and Packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ghostty.org/docs/features/shell-integration&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Shell Integration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>How to Control fdupes Deletion Order: Keep Duplicate Files by Directory Priority</title>
        <link>https://knightli.com/en/2026/05/06/fdupes-delete-duplicates-by-directory-priority/</link>
        <pubDate>Wed, 06 May 2026 09:23:09 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/06/fdupes-delete-duplicates-by-directory-priority/</guid>
        <description>&lt;p&gt;When using &lt;code&gt;fdupes&lt;/code&gt; to delete duplicate files across three directories, such as &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, and &lt;code&gt;c&lt;/code&gt;, and you want to keep &lt;code&gt;a&lt;/code&gt; first, then &lt;code&gt;b&lt;/code&gt;, and delete duplicates from &lt;code&gt;c&lt;/code&gt; first, the key is not a complex rule. It is the order of directory arguments.&lt;/p&gt;
&lt;p&gt;In non-interactive delete mode, &lt;code&gt;fdupes&lt;/code&gt; keeps the first file it sees in each duplicate group and deletes later duplicates. Therefore, directory arguments should be arranged from highest retention priority to lowest.&lt;/p&gt;
&lt;p&gt;In other words, to achieve &amp;ldquo;delete from c first, then b, and keep a as much as possible&amp;rdquo;, write the command like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fdupes -rdN a b c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The scan order is &lt;code&gt;a -&amp;gt; b -&amp;gt; c&lt;/code&gt;. When the same file exists in all three directories, the file in &lt;code&gt;a&lt;/code&gt; is found first and kept, while duplicates in &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;c&lt;/code&gt; are deleted. If only &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;c&lt;/code&gt; contain duplicates, &lt;code&gt;b&lt;/code&gt; is kept and &lt;code&gt;c&lt;/code&gt; is deleted.&lt;/p&gt;
&lt;h2 id=&#34;parameter-meaning&#34;&gt;Parameter Meaning
&lt;/h2&gt;&lt;p&gt;Common parameters are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-r&lt;/code&gt;: recursively scan subdirectories.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-d&lt;/code&gt;: delete duplicate files.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-N&lt;/code&gt;: when used with &lt;code&gt;-d&lt;/code&gt;, skip interactive confirmation, keep the first file in each duplicate group, and delete the rest.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Therefore, the basic format for automatic duplicate deletion is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fdupes -rdN 目录A 目录B 目录C
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The earlier a directory appears, the higher its retention priority. The later it appears, the more likely its duplicate files are to be deleted.&lt;/p&gt;
&lt;h2 id=&#34;preview-before-deleting&#34;&gt;Preview Before Deleting
&lt;/h2&gt;&lt;p&gt;Using &lt;code&gt;-dN&lt;/code&gt; deletes files directly, so it is better to preview duplicate groups first:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fdupes -r a b c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The output is grouped by duplicate files. In each group, the file shown earlier is the one more likely to be kept in non-interactive deletion mode.&lt;/p&gt;
&lt;p&gt;You can also view summary information:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fdupes -rm a b c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If the data is important, save the result and inspect it manually:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fdupes -r a b c &amp;gt; duplicates.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;After confirming that the order within each duplicate group matches your expectations, run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fdupes -rdN a b c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;how-subdirectories-are-handled&#34;&gt;How Subdirectories Are Handled
&lt;/h2&gt;&lt;p&gt;As long as &lt;code&gt;-r&lt;/code&gt; is enabled, &lt;code&gt;fdupes&lt;/code&gt; recursively scans all files under the directories you pass in. Retention priority is still determined by the order in which paths appear in the command.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fdupes -rdN dir_a dir_b dir_c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dir_a&lt;/code&gt; has the highest priority.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dir_b&lt;/code&gt; comes next.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dir_c&lt;/code&gt; has the lowest priority.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If &lt;code&gt;dir_a/sub1/file.txt&lt;/code&gt; and &lt;code&gt;dir_c/sub1/file.txt&lt;/code&gt; have identical content, the file under &lt;code&gt;dir_a&lt;/code&gt; is kept. If &lt;code&gt;dir_a/x/y/file.txt&lt;/code&gt; and &lt;code&gt;dir_c/file.txt&lt;/code&gt; have identical content, the file under &lt;code&gt;dir_a&lt;/code&gt; is still kept first. &lt;code&gt;fdupes&lt;/code&gt; compares file content; filenames and directory depth do not need to match.&lt;/p&gt;
&lt;h2 id=&#34;precisely-controlling-subdirectory-priority&#34;&gt;Precisely Controlling Subdirectory Priority
&lt;/h2&gt;&lt;p&gt;If you only pass parent directories, the scan order inside subdirectories is determined by &lt;code&gt;fdupes&lt;/code&gt; traversal behavior. This is enough in most cases. But if you want a specific subdirectory to have higher priority, write it explicitly before its parent directory.&lt;/p&gt;
&lt;p&gt;For example, suppose you want to keep &lt;code&gt;dir_a&lt;/code&gt; first, then keep &lt;code&gt;dir_b/special&lt;/code&gt;, then process the rest of &lt;code&gt;dir_b&lt;/code&gt;, and finally process &lt;code&gt;dir_c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fdupes -rdN dir_a dir_b/special dir_b dir_c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This makes &lt;code&gt;dir_b/special&lt;/code&gt; scan before &lt;code&gt;dir_b&lt;/code&gt;. When &lt;code&gt;dir_b&lt;/code&gt; is scanned later, files under &lt;code&gt;special&lt;/code&gt; have already been recorded, so that subdirectory effectively has higher priority than the rest of &lt;code&gt;dir_b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This pattern is useful when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;a&lt;/code&gt; is the most important baseline directory.&lt;/li&gt;
&lt;li&gt;A subdirectory inside &lt;code&gt;b&lt;/code&gt; is more important than the rest of &lt;code&gt;b&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;c&lt;/code&gt; is mainly a low-priority backup directory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The path order can be extended further:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fdupes -rdN a b/important b c/keep-first c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The rule is still the same: the earlier it appears, the more likely it is to be kept.&lt;/p&gt;
&lt;h2 id=&#34;use-a-list-for-many-directories&#34;&gt;Use a List for Many Directories
&lt;/h2&gt;&lt;p&gt;If there are many directories and subdirectories, manually writing a long command is error-prone. You can write paths into a text file such as &lt;code&gt;folders.txt&lt;/code&gt;, ordered by priority:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/path/to/dir_a
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/path/to/dir_b/sub_important
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/path/to/dir_b
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/path/to/dir_c/sub_1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/path/to/dir_c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then pass them to &lt;code&gt;fdupes&lt;/code&gt; with &lt;code&gt;xargs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cat folders.txt &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; xargs fdupes -rdN
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If paths may contain spaces, use null-separated input for better safety:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tr &lt;span class=&#34;s1&#34;&gt;&amp;#39;\n&amp;#39;&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt; &amp;lt; folders.txt &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; xargs -0 fdupes -rdN
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;important-boundaries&#34;&gt;Important Boundaries
&lt;/h2&gt;&lt;p&gt;First, &lt;code&gt;fdupes&lt;/code&gt; compares file content, not filenames. Two files with completely different names can still be treated as duplicates if their content is identical.&lt;/p&gt;
&lt;p&gt;Second, if directory &lt;code&gt;a&lt;/code&gt; contains duplicates internally, &lt;code&gt;fdupes -rdN a b c&lt;/code&gt; may also delete later duplicates inside &lt;code&gt;a&lt;/code&gt;. This command means &amp;ldquo;keep the first file according to the overall scan order&amp;rdquo;, not &amp;ldquo;never delete anything under a&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Third, by default, &lt;code&gt;fdupes&lt;/code&gt; does not follow symbolic links. If you need to handle files behind symlinks, confirm whether &lt;code&gt;-s&lt;/code&gt; is needed and whether that matches your data-safety expectations.&lt;/p&gt;
&lt;p&gt;Fourth, &lt;code&gt;fdupes&lt;/code&gt; only deletes duplicate files. It does not clean up empty directories. After deletion, if &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;c&lt;/code&gt; contain empty folders, you can run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;find b c -type d -empty -delete
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;safer-operating-habit&#34;&gt;Safer Operating Habit
&lt;/h2&gt;&lt;p&gt;If the directories contain important data, do not start with &lt;code&gt;-rdN&lt;/code&gt;. A safer workflow is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;fdupes -r a b c&lt;/code&gt; first to view duplicate groups.&lt;/li&gt;
&lt;li&gt;Confirm that the first file in each group is the one you want to keep.&lt;/li&gt;
&lt;li&gt;Then run &lt;code&gt;fdupes -rdN a b c&lt;/code&gt; for automatic deletion.&lt;/li&gt;
&lt;li&gt;After deletion, check whether empty directories need cleanup.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you are very worried about accidentally deleting files under &lt;code&gt;a&lt;/code&gt;, first clean a smaller range of low-priority directories, or export the results and filter them manually. The directory order in &lt;code&gt;fdupes&lt;/code&gt; is useful, but it is not an access-control rule. Once a path is included in the scan, duplicate files inside it may participate in deletion decisions.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;To delete duplicate files with &lt;code&gt;fdupes&lt;/code&gt; by priority, put the directories you want to keep earlier and the directories you want to delete from later.&lt;/p&gt;
&lt;p&gt;To keep &lt;code&gt;a&lt;/code&gt;, then &lt;code&gt;b&lt;/code&gt;, and delete from &lt;code&gt;c&lt;/code&gt; first:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fdupes -rdN a b c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;To give a subdirectory higher priority, write it before its parent directory:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fdupes -rdN a b/important b c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The key sentence is simple: &lt;code&gt;fdupes -dN&lt;/code&gt; keeps duplicate files that appear first and deletes duplicates that appear later. Directory order is your retention priority.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>FFmpeg `-map` Explained: Precisely Select Video, Audio, and Subtitle Streams</title>
        <link>https://knightli.com/en/2026/04/02/ffmpeg-map-parameter-guide/</link>
        <pubDate>Thu, 02 Apr 2026 23:14:03 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/04/02/ffmpeg-map-parameter-guide/</guid>
        <description>&lt;p&gt;In multi-audio and multi-subtitle workflows, &lt;code&gt;-map&lt;/code&gt; is one of FFmpeg&amp;rsquo;s most important and most frequently misused options.&lt;/p&gt;
&lt;p&gt;If you don&amp;rsquo;t explicitly specify &lt;code&gt;-map&lt;/code&gt;, FFmpeg auto-selects streams using default rules, and the output is often not what you expect. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Subtitles disappear after export&lt;/li&gt;
&lt;li&gt;The wrong language track is selected&lt;/li&gt;
&lt;li&gt;Unwanted data streams are included&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article uses common real-world scenarios to explain how &lt;code&gt;-map&lt;/code&gt; works.&lt;/p&gt;
&lt;h2 id=&#34;first-understand-what-a-stream-is&#34;&gt;First, Understand What a &amp;ldquo;Stream&amp;rdquo; Is
&lt;/h2&gt;&lt;p&gt;A container file (such as &lt;code&gt;mp4&lt;/code&gt; or &lt;code&gt;mkv&lt;/code&gt;) usually contains multiple streams, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Video streams (&lt;code&gt;v&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Audio streams (&lt;code&gt;a&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Subtitle streams (&lt;code&gt;s&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Attachment/data streams (fonts, cover art, chapters, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can inspect streams with &lt;code&gt;ffprobe&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ffprobe -hide_banner input.mkv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;basic--map-syntax&#34;&gt;Basic &lt;code&gt;-map&lt;/code&gt; Syntax
&lt;/h2&gt;&lt;p&gt;Most common pattern:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-map input_index[:stream_type][:stream_index]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0:v&lt;/code&gt;: all video streams from the 1st input&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0:a:0&lt;/code&gt;: the 1st audio stream from the 1st input&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1:s:1&lt;/code&gt;: the 2nd subtitle stream from the 2nd input&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;input_index&lt;/code&gt; starts from &lt;code&gt;0&lt;/code&gt;, based on &lt;code&gt;-i&lt;/code&gt; order&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stream_index&lt;/code&gt; also starts from &lt;code&gt;0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;practical-examples&#34;&gt;Practical Examples
&lt;/h2&gt;&lt;h3 id=&#34;1-video-from-a-audio-from-b&#34;&gt;1) Video from A, audio from B
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ffmpeg -i english.mp4 -i french.mp3 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -map 0:v:0 -map 1:a:0 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -c:v copy -c:a aac &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  french.mp4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Meaning:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use the first video stream from &lt;code&gt;english.mp4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use the first audio stream from &lt;code&gt;french.mp3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Merge into &lt;code&gt;french.mp4&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;2-keep-all-streams-from-input-1-then-add-one-more-audio-track&#34;&gt;2) Keep all streams from input 1, then add one more audio track
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ffmpeg -i english.mp4 -i french.mp3 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -map &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; -map 1:a:0 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -c copy &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  english-french.mp4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Meaning:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-map 0&lt;/code&gt; keeps all streams from the first input&lt;/li&gt;
&lt;li&gt;Then append the first audio stream from the second input&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;two-useful-advanced-tricks&#34;&gt;Two Useful Advanced Tricks
&lt;/h2&gt;&lt;h3 id=&#34;1-negative-mapping-exclude-unwanted-streams&#34;&gt;1) Negative mapping: exclude unwanted streams
&lt;/h3&gt;&lt;p&gt;For example, keep everything from input 1 but remove its second audio stream:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ffmpeg -i input.mkv -map &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; -map -0:a:1 -c copy output.mkv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;2-optional-mapping-dont-fail-when-a-stream-is-missing&#34;&gt;2) Optional mapping: don&amp;rsquo;t fail when a stream is missing
&lt;/h3&gt;&lt;p&gt;If some files may not have subtitles, use &lt;code&gt;?&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ffmpeg -i input.mp4 -map 0:v -map 0:a -map 0:s? -c copy output.mp4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;0:s?&lt;/code&gt; means: map subtitles if present; otherwise skip without error.&lt;/p&gt;
&lt;h2 id=&#34;common-pitfalls&#34;&gt;Common Pitfalls
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Once you use &lt;code&gt;-map&lt;/code&gt;, FFmpeg stops automatic stream selection, so you must map everything you need.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-c copy&lt;/code&gt; only remuxes without transcoding. If the target container doesn&amp;rsquo;t support a codec, it still fails.&lt;/li&gt;
&lt;li&gt;With multiple inputs, index mistakes are common. Input indices are determined only by &lt;code&gt;-i&lt;/code&gt; order.&lt;/li&gt;
&lt;li&gt;For robust scripts, inspect with &lt;code&gt;ffprobe&lt;/code&gt; first, then generate &lt;code&gt;-map&lt;/code&gt; dynamically.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;The core idea of &lt;code&gt;-map&lt;/code&gt; is simple: explicitly tell FFmpeg which input to use, what stream type to pick, and which stream index to select.&lt;/p&gt;
&lt;p&gt;Once you master this, you can reliably handle complex cases like multi-audio, multi-subtitle, and cross-file stream composition.&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
