The man
page doesn't give me much hope, but I'm hoping it's an undocumented (and/or GNU-specific) feature.

- 3,549
6 Answers
The moreutils package from ubuntu (and also debian) has a program called sponge
, which sort-of also solves your problem.
From man sponge:
sponge reads standard input and writes it out to the specified file. Unlike a shell redirect, sponge soaks up all its input before opening the output file. This allows constricting pipelines that read from and write to the same file.
Which would let you do something like:
cut -d <delim> -f <fields> somefile | sponge somefile

- 15,462

- 1,244
- 7
- 7
You can't. Either use ed or GNU sed or perl, or do what they do behind the scenes, which is to create a new file for the contents.
ed
, portable:
ed foo <<EOF
1,$s/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/
w
q
EOF
GNU sed
:
sed -i -e 's/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/' foo
Perl:
perl -i -l -F, -pae 'print @F[1,3]' foo
cut
, creating a new file (recommended, because if your script is interrupted, you can just run it again):
cut -d , -f 1,3 <foo >foo.new &&
mv -f foo.new foo
cut
, replacing the file in place (retains the ownership and permissions of foo
, but needs protection against interruptions):
cp -f foo foo.old &&
cut -d , -f 1,3 <foo.old >foo &&
rm foo.old
I recommend using one of the cut
-based methods. That way you don't depend on any non-standard tool, you can use the best tool for the job, and you control the behavior on interrupt.

- 829,060
I don't think that is possible using cut
alone. I couldn't find it in the man or info page. You can do something such as
mytemp=$(mktemp) && cut -d" " -f1 file > $mytemp && mv $mytemp file
mktemp
makes you a relatively safe temporary file that you can pipe the cut
output into.

- 46,160
Well, since cut
produces less output than it reads, you can do:
cut -c1 < file 1<> file
That is, make its stdin the file
open in read-only mode and its stdout the file
open in read+write mode without truncation (<>
).
That way, cut
will just overwrite the file over itself. However, it will leave the rest of the file untouched. For instance, if file
contains:
foo
bar
The output will become:
f
b
bar
The f\nb\n
have replaced foo\n
, but bar
is still there. You'd need to truncate the file after cut
has finished.
With ksh93
, you can do it with its <>;
operator which acts like <>
except that if the command succeeds, ftruncate()
is called on the file descriptor. So:
cut -c1 < file 1<>; file
With other shells, you'd need to do the ftruncate()
via some other means like:
{ cut -c1 < file; perl -e 'truncate STDOUT, tell STDOUT';} 1<> file
though invoking perl
just for that is a bit overkill here especially considering that perl
can easily do that cut
's job like:
perl -pi -e '$_ = substr($_, 0, 1)' file
Beware that with all methods that involve actual in-place rewriting, if the operation is interrupted midway, you'll end up with a corrupted file. Using a temporary second file avoids this problem.

- 829,060

- 544,893
.old
method for in-place changes,echo "$(cut -d , -f 1,3 <foo)" > foo
– GypsyCosmonaut Oct 26 '18 at 03:10cut -d , -f 1,3 foo > foo.new
rm foo
mv foo.new foo
– LoMaPh Dec 21 '18 at 01:13rm foo
. And you shouldn't callrm foo
, becausemv foo.new foo
is atomic: it removes the old version and puts the new version in place at the same time. – Gilles 'SO- stop being evil' Dec 21 '18 at 07:41cp -f foo foo.new && cut -d , -f 1,3 <foo >foo.new && mv -f foo.new foo
to retain perms/ownership AND protect against interruptions? – stackprotector Aug 17 '21 at 10:46cut -d , -f 1,3 <foo >foo.new && chmod --reference foo foo.new && chown --reference foo foo.new && mv -f foo.new foo
to retain perms/ownership and protect against interruptions. Thx for clarification! – stackprotector Aug 17 '21 at 11:34