** New features
+ cut, head, tail now have -z, --zero-terminated options to work with
+ NUL delimited items.
+
dd now summarizes sizes in --human-readable format too, not just --si.
E.g., "3441325000 bytes (3.4 GB, 3.2 GiB) copied". It omits the summaries
if they would not provide useful information, e.g., "3 bytes copied".
Its status=progress output now uses the same format as ordinary status,
perhaps with trailing spaces to erase previous progress output.
- head, tail now have -z, --zero-terminated options to work with
- NUL delimited items.
-
md5sum now supports the --ignore-missing option to allow
verifying a subset of files given a larger list of checksums.
This also affects sha1sum, sha224sum, sha256sum, sha384sum and sha512sum.
/* The delimiter character for field mode. */
static unsigned char delim;
+/* The delimiter for each line/record. */
+static unsigned char line_delim = '\n';
+
/* True if the --output-delimiter=STRING option was specified. */
static bool output_delimiter_specified;
{"only-delimited", no_argument, NULL, 's'},
{"output-delimiter", required_argument, NULL, OUTPUT_DELIMITER_OPTION},
{"complement", no_argument, NULL, COMPLEMENT_OPTION},
+ {"zero-terminated", no_argument, NULL, 'z'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
-s, --only-delimited do not print lines not containing delimiters\n\
--output-delimiter=STRING use STRING as the output delimiter\n\
the default is to use the input delimiter\n\
+"), stdout);
+ fputs (_("\
+ -z, --zero-terminated line delimiter is NUL, not newline\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
c = getc (stream);
- if (c == '\n')
+ if (c == line_delim)
{
- putchar ('\n');
+ putchar (c);
byte_idx = 0;
print_delimiter = false;
current_rp = frp;
else if (c == EOF)
{
if (byte_idx > 0)
- putchar ('\n');
+ putchar (line_delim);
break;
}
else
size_t n_bytes;
len = getndelim2 (&field_1_buffer, &field_1_bufsize, 0,
- GETNLINE_NO_LIMIT, delim, '\n', stream);
+ GETNLINE_NO_LIMIT, delim, line_delim, stream);
if (len < 0)
{
free (field_1_buffer);
{
fwrite (field_1_buffer, sizeof (char), n_bytes, stdout);
/* Make sure the output line is newline terminated. */
- if (field_1_buffer[n_bytes - 1] != '\n')
- putchar ('\n');
- c = '\n';
+ if (field_1_buffer[n_bytes - 1] != line_delim)
+ putchar (line_delim);
+ c = line_delim;
}
continue;
}
fwrite (field_1_buffer, sizeof (char), n_bytes - 1, stdout);
/* With -d$'\n' don't treat the last '\n' as a delimiter. */
- if (delim == '\n')
+ if (delim == line_delim)
{
int last_c = getc (stream);
if (last_c != EOF)
}
found_any_selected_field = true;
- while ((c = getc (stream)) != delim && c != '\n' && c != EOF)
+ while ((c = getc (stream)) != delim && c != line_delim && c != EOF)
{
putchar (c);
prev_c = c;
}
else
{
- while ((c = getc (stream)) != delim && c != '\n' && c != EOF)
+ while ((c = getc (stream)) != delim && c != line_delim && c != EOF)
{
prev_c = c;
}
}
/* With -d$'\n' don't treat the last '\n' as a delimiter. */
- if (delim == '\n' && c == delim)
+ if (delim == line_delim && c == delim)
{
int last_c = getc (stream);
if (last_c != EOF)
if (c == delim)
next_item (&field_idx);
- else if (c == '\n' || c == EOF)
+ else if (c == line_delim || c == EOF)
{
if (found_any_selected_field
|| !(suppress_non_delimited && field_idx == 1))
{
- if (c == '\n' || prev_c != '\n' || delim == '\n')
- putchar ('\n');
+ if (c == line_delim || prev_c != line_delim
+ || delim == line_delim)
+ putchar (line_delim);
}
if (c == EOF)
break;
delim = '\0';
have_read_stdin = false;
- while ((optc = getopt_long (argc, argv, "b:c:d:f:ns", longopts, NULL)) != -1)
+ while ((optc = getopt_long (argc, argv, "b:c:d:f:nsz", longopts, NULL)) != -1)
{
switch (optc)
{
suppress_non_delimited = true;
break;
+ case 'z':
+ line_delim = '\0';
+ break;
+
case COMPLEMENT_OPTION:
complement = true;
break;
['newline-23', "-d'\n'", '-f1-', '--ou=:', {IN=>"a\nb\n"}, {OUT=>"a:b\n"}],
['newline-24', "-d'\n'", '-f1,2', '--ou=:', {IN=>"a\nb\n"}, {OUT=>"a:b\n"}],
+ # --zero-terminated
+ ['zerot-1', "-z", '-c1', {IN=>"ab\0cd\0"}, {OUT=>"a\0c\0"}],
+ ['zerot-2', "-z", '-c1', {IN=>"ab\0cd"}, {OUT=>"a\0c\0"}],
+ ['zerot-3', '-z -f1-', {IN=>""}, {OUT=>""}],
+ ['zerot-4', '-z -d:', '-f1', {IN=>"a:1\0b:2"}, {OUT=>"a\0b\0"}],
+ ['zerot-5', '-z -d:', '-f1-', {IN=>"a1:\0:"}, {OUT=>"a1:\0:\0"}],
+ ['zerot-6', "-z -d ''", '-f1,2', '--ou=:', {IN=>"a\0b\0"}, {OUT=>"a:b\0"}],
+
# New functionality:
['out-delim1', '-c1-3,5-', '--output-d=:', {IN=>"abcdefg\n"},
{OUT=>"abc:efg\n"}],