With systemd units that have arguments, hypens and other specifiers are replaced with forward slashes.

Some unit names reflect paths existing in the file system namespace. Example: a device unit dev-sda.device refers to a device with the device node /dev/sda in the file system namespace. If this applies, a special way to escape the path name is used, so that the result is usable as part of a filename. Basically, given a path, "/" is replaced by "-", and all other characters which are not ASCII alphanumerics are replaced by C-style "\x2d" escapes

-- freedesktop.org

I was trying to pass in an argument with a hyphen in it and I noticed that the systemd unit doesn't replace my hyphens with a slash. So are hyphens not always relaced? Or am I just interpreting things incorrectly?

Basically I want to pass in a string to a systemd unit that passes a string to the executable I'm running in the unit.

For example:

Say I have a unit [email protected], inside the unit I want to execute :

/usr/local/bin/my_script param-with-hyphen

If I try to pass in the argument with a hyphen to the following unit like this:

$ systemctl start [email protected]

ExecStart=/usr/local/bin/my_script %i

Wont it convert the string to param/with/hyphen?

In my testing the hyphen is not replaced.

I made a unit: /etc/systemd/system/[email protected]

Description=Test arg %i

ExecStart=/usr/bin/echo "arg: %i"

and ran systemctl start testunit@test-hyphen

The result doesn't replace the hyphen:

$ journalctl -u testunit@test-hyphen
Journal file /var/log/journal/f41c5d772fa24834926605125d59db1b/user-1000@4cc6a20c4391418eb972f65e6ecfafbe-000000000000043c-0005351d59c7b07b.journal is truncated, ignoring file.
-- Logs begin at Fri 2016-06-10 18:15:25 PDT, end at Sat 2016-09-24 23:12:42 PDT
Sep 24 23:12:25 Archon systemd[1]: Started Test arg test-hyphen.
Sep 24 23:12:25 Archon echo[6302]: arg: test-hyphen
  • 1
    In the documentation you've linked, I don't see this behaviour described; could you edit your question and quote the relevant text? Sep 25, 2016 at 4:11
  • just use systemd-escape(1)
    – llua
    Sep 25, 2016 at 7:26

2 Answers 2


You misread the documentation:

Basically, given a path, "/" is replaced by "-"

Slashes in a filesystem path are replaced by dashes, but it says nothing about dashes being replaced by slashes... which is why in your test, the dashes remain as is. Although what is probably happening, is your dashes are being replaced with \x2d, which is interpreted as - as it moves down the pipeline.

all other characters which are not ASCII alphanumerics are replaced by C-style "\x2d" escapes

The section on "Specifiers" doesn't seem to have much relevance here, other than allowing you to direct how your arguments are or are not escaped.


The document you linked to has the explanation right at the table: the escaping isn't undone automatically, but you have to ask for it specifically:

"%i" Instance name: For instantiated units: this is the string between the "@" character and the suffix of the unit name.
"%I" Unescaped instance name: Same as "%i", but with escaping undone

Using %I instead of %i, you should see the dashes changed to hyphens as you describe.

(That wording is somewhat vague to me, though. "unescaped" could be interpreted to mean that the value isn't escaped, but it means here that the escaping is undone.)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .