On 09/01/2025 15:34, Daniel Hofstetter wrote:
Hi,While experimenting with csplit I noticed the following behavior: if the input is empty, an empty xx00 split file is created: $ printf "" | csplit - 5 csplit: input disappeared $ ls xx00 xx00 However, if the input is not empty, no such file is created: $ printf "a" | csplit - 5 csplit: ‘5’: line number out of range 1 $ ls xx00 ls: cannot access 'xx00': No such file or directory Is this a bug or a feature?
Looks like a bug. I can't think why the "input disappeared" case is handled separately. I'll push the attached later to treat it like the second case above. cheers, Pádraig
From 268b40b276e43561006344e6980aa628b96f842a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com> Date: Thu, 9 Jan 2025 19:29:01 +0000 Subject: [PATCH] csplit: avoid extraenous output files given empty input * src/csplit.c (get_first_line_in_buffer): Don't exit here upon empty input, rather indicate no input in the return to let callers handle in a more consistent fashion. * NEWS: Mention the bug fix. * tests/csplit/csplit.sh: Add a test case. Reported by Daniel Hofstetter. --- NEWS | 3 +++ src/csplit.c | 11 +++++++---- tests/csplit/csplit.sh | 10 ++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 793745de6..4a0c1da98 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,9 @@ GNU coreutils NEWS -*- outline -*- cp,mv --update no longer overrides --interactive or --force. [bug introduced in coreutils-9.3] + csplit no longer creates empty files given empty input. + [This bug was present in "the beginning".] + ls and printf fix shell quoted output in the edge case of escaped first and last characters, and single quotes in the string. [bug introduced in coreutils-8.26] diff --git a/src/csplit.c b/src/csplit.c index c65e3d418..9119dcf5a 100644 --- a/src/csplit.c +++ b/src/csplit.c @@ -494,13 +494,14 @@ load_buffer (void) } } -/* Return the line number of the first line that has not yet been retrieved. */ +/* Return the line number of the first line that has not yet been retrieved. + Return 0 if no lines available. */ static intmax_t get_first_line_in_buffer (void) { if (head == nullptr && !load_buffer ()) - error (EXIT_FAILURE, errno, _("input disappeared")); + return 0; return head->first_available; } @@ -627,7 +628,7 @@ write_to_file (intmax_t last_line, bool ignore, int argnum) first_line = get_first_line_in_buffer (); - if (first_line > last_line) + if (! first_line || first_line > last_line) { error (0, 0, _("%s: line number out of range"), quote (global_argv[argnum])); @@ -698,7 +699,9 @@ process_line_count (const struct control *p, intmax_t repetition) if (no_more_lines () && suppress_matched) handle_line_error (p, repetition); - linenum = get_first_line_in_buffer (); + if (!(linenum = get_first_line_in_buffer ())) + handle_line_error (p, repetition); + while (linenum++ < last_line_to_save) { struct cstring *line = remove_line (); diff --git a/tests/csplit/csplit.sh b/tests/csplit/csplit.sh index 021b08ae2..e3c16c1cc 100755 --- a/tests/csplit/csplit.sh +++ b/tests/csplit/csplit.sh @@ -100,4 +100,14 @@ printf 'x%8199s\nx\n%8199s\nx\n' x x > in csplit in '/x\{1\}/' '{*}' > /dev/null || fail=1 cat xx?? | compare - in || fail=1 +# Ensure file not created for empty input +# which was the case with coreutils <= 9.5 +rm -f in && touch in || framework_failure_ +csplit in 5 > out 2> err && fail=1 +test -f xx00 && fail=1 +cat <<\EOF > experr +csplit: '5': line number out of range +EOF +compare experr err || fail=1 + Exit $fail -- 2.47.1