How to `touch` and `cat` file named `-`
Use an explicit path to the file:
touch ./-
cat ./-
GNU touch
treats a file operand of -
specially:
A FILE argument string of
-
is handled specially and causestouch
to change the times of the file associated with standard output.
For cat
, the POSIX standard specifies that a file operand -
should be interpreted as a request to read from standard input.
The double-dash convention is still in effect, but it's not for signalling the end of arguments but the end of options. In neither of these cases would -
be taken as an option (a lone -
can not be an option) but as an operand ("file name argument").
Regarding your last question:
To protect the contents of a variable against being interpreted as a set of options when using it as
utility "$variable"
use
utility -- "$variable"
Note that if the utility is cat
, sed
, awk
, paste
, sort
and possibly a few others (or GNU touch
), and $variable
is -
, this will still cause the utility to do its special processing since, as said above, -
is not an option. Instead, make provisions so that filenames, if they may start with or are equal to -
, are preceded by a path, for example ./
for files in the current working directory.
A good habit is to use
for filename in ./*; do
rather than
for filename in *; do
for example.
![Tom Hale](https://lh4.googleusercontent.com/-kpRTzH5zyzs/AAAAAAAAAAI/AAAAAAAAAAA/ICc26Nac6mY/photo.jpg?sz=256)
Tom Hale
Updated on September 18, 2022Comments
-
Tom Hale almost 2 years
How do I use GNU
touch
to update a file called-
?How do I use GNU
cat
to display a file called-
?
I'm running:
% cat --version | head -n1 cat (GNU coreutils) 8.29 % touch --version | head -n1 touch (GNU coreutils) 8.29
Firstly,
touch
:% touch - % ls -l total 0 % touch -- - % ls -l -- - ls: cannot access '-': No such file or directory
Ok, I'll give up on creating a file with
touch
. Let's create it withdate
instead:% date > - % ls -l - -rw-r--r-- 1 ravi ravi 29 Sep 8 19:54 - %
Now, let's try to
cat
it:% cat - % # I pressed ^D % cat -- - % # Same again - I pressed ^D
I know I can work around with:
% > -
and
% cat < -
But why don't these GNU utils support the convention that
--
means that everything following is treated as a non-option?How do I use these tools in the general case, for example I have a variable with the contents
-
? -
Tom Hale almost 6 yearsIt seems the way for absolute belts and braces would be to do
cat "$(readlink -f "$file")"
-
Tom Hale almost 6 yearsWhat about the
touch
case though? -
Kusalananda almost 6 years@TomHale no.
readlink -f
is not portable. What about thetouch
case? -
Tom Hale almost 6 yearsSo
[ "$file" = - ] && file=./-
is needed before each invocation of GNUcat
andtouch
for the truly paranoid? Any nicer ways? -
Kusalananda almost 6 years@TomHale If you're looping over files in a directory, make a habit of using
for file in ./*
or similar, instead offor file in *
. -
Stéphane Chazelas almost 6 years@TomHale, Also
"$(readlink -f -- "$file")"
(here adding the missing--
) strips trailing newline characters so wouldn't work for files that end in newline. Also note that with GNUreadlink
at least,readlink -f foo/bar
wherefoo
doesn't exist returns an empty output, exit status 1 and no error message.