BurntSushi / ripgrep

ripgrep recursively searches directories for a regex pattern while respecting your gitignore
The Unlicense
48.83k stars 2.01k forks source link

rg '<,'> file.txt | will clear the contents of file.txt #2887

Closed AnthonyGithubCorner closed 2 months ago

AnthonyGithubCorner commented 2 months ago

Please tick this box to confirm you have reviewed the above.

What version of ripgrep are you using?

ripgrep 14.1.1

features:+pcre2 simd(compile):+SSE2,+SSSE3,-AVX2 simd(runtime):+SSE2,+SSSE3,+AVX2

PCRE2 10.43 is available (JIT is available)

How did you install ripgrep?

Homebrew

What operating system are you using ripgrep on?

MacOS 14.6.1

Describe your bug.

ripgrep clears the entire content of the file or will replace the file with random garbage. This happens when running the mistake command rg '<,'> file.txt

What are the steps to reproduce the behavior?

You will see that the file is completely cleared after issuing the command. I would be careful debugging this problem as it might result in data lost.

echo hello >> hello.txt
cat hello.txt
rg '<,'> hello.txt
cat hello.txt 

What is the actual behavior?

rg --debug '<,'> hello.txt
rg: DEBUG|rg::flags::parse|crates/core/flags/parse.rs:97: no extra arguments found from configuration file
rg: DEBUG|rg::flags::hiargs|crates/core/flags/hiargs.rs:1083: number of paths given to search: 0
rg: DEBUG|rg::flags::hiargs|crates/core/flags/hiargs.rs:1108: using heuristics to determine whether to read from stdin or search ./ (is_readable_stdin=false, stdin_consumed=false, mode=Search(Standard))
rg: DEBUG|rg::flags::hiargs|crates/core/flags/hiargs.rs:1118: heuristic chose to search ./
rg: DEBUG|rg::flags::hiargs|crates/core/flags/hiargs.rs:1269: found hostname for hyperlink configuration: something_hidden.lan
rg: DEBUG|rg::flags::hiargs|crates/core/flags/hiargs.rs:1279: hyperlink format: ""
rg: DEBUG|rg::flags::hiargs|crates/core/flags/hiargs.rs:174: using 8 thread(s)
rg: DEBUG|grep_regex::config|/private/tmp/ripgrep-20240910-11501-ez7f5q/ripgrep-14.1.1/crates/regex/src/config.rs:175: assembling HIR from 1 fixed string literals
rg: DEBUG|globset|crates/globset/src/lib.rs:453: built glob set; 0 literals, 0 basenames, 12 extensions, 0 prefixes, 0 suffixes, 0 required extensions, 0 regexes

What is the expected behavior?

I ended up running the command trying to see if I can pass through selected content in vim to ripgrep. I wasn't too worried but imagine my surprise when something I did cleared the file I was searching. I narrowed it down to this command. The expected behaviour is no matches and the file isn't touched.

okdana commented 2 months ago

This is a shell command typo that ripgrep can't do anything about. The shell interprets the quoting and redirect syntax before ripgrep is even executed, all it knows is that you've told it to search for the pattern <, and output the results to a file. Even if it could see the raw shell command, it's perfectly valid, so there's no way for it (or the shell) to figure out that you meant to type something else

If you want, you can enable the noclobber option in your shell profile to make it so that > isn't allowed to overwrite the contents of existing files:

# In bash:
set -o noclobber

# In zsh:
setopt no_clobber
# Also set this to make it work like bash, where you can still use >> to create files:
setopt append_create
# ETA: Also set this to make it work like bash, where you can't use > to overwrite *empty* files:
setopt no_clobber_empty

If you do this you will have to remember to use >| instead of > whenever you want to actually overwrite a file