21

Recently I'm echoing short sentences to a tree_hole file.

I was using echo 'something' >> tree_hole to do this job.

But I was always worried of what if I mis-input of > instead of >>, since I did this often.

So I made a global bash func of my own in the bashrc:

function th { echo "$1" >> /Users/zen1/zen/pythonstudy/tree_hole; }
export -f th

But I'm wondering if there is another simple way to append lines to the end of a file. Because I may need to use that often in other occasions.

Is there any?

Zen
  • 7,537
  • 9
    Will you not forget you are using the work-around each time you enter > ? Once I had an alias rm="rm -i" and in an other environment wrote rm * waiting for the confirmation questions. You are learning dangerous habits ! – Walter A Jan 12 '15 at 12:37
  • 9
    @WalterA er, his "workaround" doesn't let him type > instead of >>, he just runs "th some_sentence", which does nothing if the alias is undefined. – Random832 Jan 12 '15 at 14:11
  • 1
    @Ranom832 correct for his th work-around. The warning is for a "solution" like noclobber. When he uses something like noclobber in his normal shell he might use > when he is temporary root and wants to append something. – Walter A Jan 12 '15 at 14:27
  • 7
    @Random832 & WalterA I normally don't say anything about this when I see it, but i figured maybe a friendly notice once in a while could be useful. Zen's user profile doesn't have much detail, so I'm not sure if you really know that his "workaround" is the correct form. Maybe you should say their "workaround" or the OP's "workaround". Perhaps you know Zen personally and you therefore know that his is correct, in which case, please pardon the noise. Not a big deal, I just mention it because I know I wouldn't have appreciated it very much if you had used that form to talk about me. – Celada Jan 12 '15 at 14:56
  • @WalterA I agree about dangerous habits. I usually use mv -i for safety, but I've trained myself to type the option, not alias it. – Celada Jan 12 '15 at 14:58
  • @WalterA, I'm not quite understand your worrying. Since I adopted Celada's plan, I will only be used to >| when I want to write something to a file, and still I'll use >> to append something to files. The chance to mis-operate won't improve. – Zen Jan 13 '15 at 02:48
  • 1
    @Zen, You wrote you are worried to mis-input > instead of >>. Celada's plan will take away the risks in your environment, and is a good solution for you. When you are helping your neighbour (who doesn't has noclobber or is using ksh) and you lost your attention for one or two > characters, you might accidentally overwrite one of his files. So everytime you get the noclobber warning in your own environment, thank God or Celada, say to yourself: Ohh, be carefully please!, shake your head and wait two seconds. – Walter A Jan 13 '15 at 09:29

6 Answers6

46

Set the shell's noclobber option:

bash-3.2$ set -o noclobber
bash-3.2$ echo hello >foo
bash-3.2$ echo hello >foo
bash: foo: cannot overwrite existing file
bash-3.2$ 
Celada
  • 44,132
  • 3
    This is the definitive answer. Note that you can still overwrite the file if you force it with >|. zsh enables this behaviour by default. – orion Jan 12 '15 at 09:17
  • 1
    @orion How do you en/disable it in zsh? I don't recall explicitly disabling it, but overwriting works fine on my zsh. – muru Jan 12 '15 at 09:22
  • 2
    It's setopt noclobber and setopt clobber. It appears it isn't exactly "default", it depends on the config files that are shipped with your distro. – orion Jan 12 '15 at 09:36
  • @muru should work with set [+-]C for any modern shell – mikeserv Jan 12 '15 at 10:14
  • Yes, this is great, to replace > by >|, it really fixed the potential mis-input. But one more question, how should I cancel the set -o noclobber, since I tried set -o clobber, which didn't work. – Zen Jan 12 '15 at 10:18
  • 3
    @Zen set +o noclobber in bash, or set +C. – Ruslan Jan 12 '15 at 10:29
6

If you are worried your file will be damaged by > operator you can change your file attribute to append only:
In ext2/ext3/ext4 filesystem: chattr +a file.txt
In XFS filesystem: echo chattr +a | xfs_io file.txt

And if you want a function, I made a function for myself already (I used it in service file for logging outputs), You can change it for your purpose:

# This function redirect logs to file or terminal or both!
#@ USAGE: log option data
# To the file     -f file
# To the terminal -t
function log(){
        read -r data       # Read data from pipe line

        [[ -z ${indata} ]] && return 1    # Return 1 if data is null

        # Log to /var/log/messages
        logger -i -t SOFTWARE ${data}

        # While loop for traveling on the arguments
        while [[ ! -z "$*" ]]; do
                case "$1" in
                        -t)
                                # Writting data to the terminal
                                printf "%s\n" "${data}"
                                ;;
                        -f) 
                                # Writting (appending) data to given log file address
                                fileadd=$2
                                printf "%s %s\n" "[$(date +"%D %T")] ${data}" >> ${fileadd}
                                ;;
                        *)
                                ;;
                esac
                shift           # Shifting arguments
        done
}
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
  • 2
    There are a few problems with this script. 1) You should generally put double quotes around parameter expansions (stuff that starts with a $) to prevent globbing, word splitting and related whitespace problems. The online ShellCheck app can catch this and various other problems in bash scripts. On a related note "$@" is much safer than $*. – PM 2Ring Jan 12 '15 at 10:39
  • 3
  • You should normally call the read command with the -r option to prevent any backslashes in the input from escaping the following character. 3) It's usual in bash scripts to use lower case for script variable names since ALL UPPER CASE is used for system variables. So if you use upper case for your own variables you will confuse people who read your code, and you may accidentally clobber a system variable that you want to use later in the script. And if you source the script, it will clobber the variables for subsequent commands.
  • – PM 2Ring Jan 12 '15 at 10:44
  • 3
  • echo is handy for printing fixed strings, but it can do unexpected things with arbitrary data, especially on GNU systems. It's far safer to use printf. See http://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo for more info, especially Stéphane Chazelas's answer.
  • – PM 2Ring Jan 12 '15 at 10:52
  • 3
    @PM 2Ring, Today I learned many things from you, Thanks a lot.. I will fix them as soon as possible. – Sepahrad Salour Jan 12 '15 at 12:43
  • @PM 2Ring, Post edited. Thank you again. – Sepahrad Salour Jan 13 '15 at 15:08
  • 1
    Nice work, Sepahrad! – PM 2Ring Jan 14 '15 at 01:30