1

I was trying to replace all instances of "unix"(ignore cases) to "oracle". So, I cat the "testfile2" and pipe and after sed I redirected back to the same file "testfile2". But the file becomes empty. Can someone please help debug.

bash-3.2$ cat testfile2
uniX
udfi
unix
UNix
UNIX
Unix
ockcl
cunci

bash-3.2$ cat testfile2 |tr [A-Z] [a-z] |sed 's/unix/oracle/g' > testfile2
bash-3.2$ cat testfile2
bash-3.2$

I was able to get a workaround using a tee as follows, but couldn't figure why redirection didn't work.

bash-3.2$ cat testfile2 |tr [A-Z] [a-z] |sed 's/unix/oracle/g' |tee  testfile2
oracle
udfi
oracle
oracle
oracle
oracle
ockcl
cunci

bash-3.2$ cat testfile2
oracle
udfi
oracle
oracle
oracle
oracle
ockcl
cunci

I'm using bash version 3.2.57(1)-release (solaris2.10)

amar
  • 11
  • 1

1 Answers1

3

cat testfile2 |tr [A-Z] [a-z] |sed 's/unix/oracle/g' > testfile2

When the shell sees > testfile2 it truncates the file to zero bytes - this is done before anything else. It is not done "after sed" but before it! The fact that you put the redirection on the right is irrelevant (most people do that, but actually you can put it almost anywhere).

Redirect to a different filename (e.g. testfile2.tmp) then use mv to rename it after your command runs successfully.

Edit:

As @tripleee points out, [A-Z] [a-z] is wrong. tr does not use regular expression or glob constructs (wildcards), the square brackets would mean to translate square brackets, if they were inside quotes.

But they are not inside quotes, so the [A-Z] [a-z] will be interpreted by the shell and will be substituted for filenames. However that will only happen if you have single character filenames in the current directory - unlikely but possible. tr 'A-Z' 'a-z' is correct.

cdarke
  • 42,728
  • 8
  • 80
  • 84
  • 1
    Of course, [the `cat` is completely superfluous](http://www.iki.fi/era/unix/award.html) – tripleee Nov 09 '17 at 09:57
  • 2
    Also, the brackets are not useful with `tr` and if you don't quote them properly, they could be expanded as wildcards by the shell. You mean `tr 'A-Z' 'a-z'` plain and simple (where the quoting is now less crucial, but included for good taste). – tripleee Nov 09 '17 at 09:59
  • @trpleee Normally I would agree with the `cat``, but `tr` does not take a filename as an argument - it is not a filter program. There are other ways to avoid the `cat`, but none of that is relevant to the question. – cdarke Nov 09 '17 at 10:01
  • 1
    Proliferating the useless `cat` antipattern is a disservice to the community. It's not a big deal here but rewriting it as `tr A-Z a-z – tripleee Nov 09 '17 at 10:05
  • @tripleee: point taken, I agree. – cdarke Nov 09 '17 at 10:08