Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am trying to remove all files that have a hexadecimal digit in the first two digits, so I am using the following expression:

ls | grep -Z '^[0-9a-f][0-9a-f]' | xargs -0 rm

However, the terminal outputs the error:

xargs: argument line too long

To double-check, I ran:

ls | grep -Z '^[0-9a-f][0-9a-f]' 

which outputs all of the files that I want to delete.

Why am I getting this error? Additionally, how can I delete these files?

Also, my file names are similar to the following:

ffc1abfa3149067e990620dbecfa96d325fbbd
ffcc72282168e33110ecf436e2726a5f901ca6
ffd010299a02ded0a8d41ee1ccc242f2193df2
ffd27295acbe3d35088a5a754f5593eac6a0ae
ffd332a39f7be05d58863fe3bf55d7aba68b69
ffd7ba85b0577b90c0fb1b3922303c486127d4
ffdb37718feaf64c404a6c2a3648f15cdf27b1
ffdbffe5b187c8a73d15da9e5f6cc0fb8d4df3
ffdd8c340650848759c7e59f90f8c112ac33ce
ffde57cb4ba9b69531a3b3f2c6588d2802f71b
ffdeb529353a85b642efa1404aa27e58982da1
ffe0bec99e3e64c61dd45e404c8ccf12d7bea5
ffe58837e9d976499781de17628f2f41e16c9a
ffee6887889924583762e43d5a6b9cd29b6690
fff0b6886aff6cb4073742fbf7bcc1b47d9b45

Perhaps the file names themselves are too long for xargs?

share|improve this question

3 Answers 3

up vote 5 down vote accepted

-Z is to output a NUL after each file name with grep -l, not to change the newlines to NULs in the lines it outputs. So xargs -0 sees only one huge record (with several newline characters in it) as there's no NUL delimited, so that's only one argument to pass to rm and it probably is bigger than the maximum size of an argument (128kB on Linux) and anyway there's no such file called ...ffd7ba85b0577b90c0fb1b3922303c486127d4<newline>...fff0b6886aff6cb4073742fbf7bcc1b47d9b45.

Simply do:

rm [0-9a-f][0-9a-f]*

Or if the list is too big:

printf '%s\0' [0-9a-f][0-9a-f]* | xargs -r0 rm

Or with zsh:

autoload zargs        # best in ~/.zshrc
setopt extendedglob   # ditto

zargs [0-9a-f](#c2)* -- rm

Or with ksh93:

command -x rm {2}([0-9a-f])*

Or:

find . ! -name . -prune -name '[0-9a-f][0-9a-f]*' -exec rm {} +

Beware that in non-C locales [a-f] may match more than [abcdef].

share|improve this answer
    
Only 5 solutions, pfft. –  krowe Aug 19 at 1:39

I'd suggest changing your selection of commands to something like:

 find . -name '^[0-9a-f][0-9a-f]' -print0 | xargs -0 rm

or another alternative

 find . -name '^[0-9a-f][0-9a-f]' -exec rm {} \;
share|improve this answer
    
There's no point using the non-standard -print0/xargs -0 over the standard -exec {} +. No point using -exec rm {} \; either as rm can take more than one argument. What goes after -name is a file name pattern, not a regexp. Some find implementations support a -regex, but the match is on the full path and is anchored already. –  Stéphane Chazelas Aug 19 at 6:09

You may be running up against a file name limit depending on your file system type. See:

http://en.m.wikipedia.org/wiki/Comparison_of_file_systems

Specifically, the section on "Limits"

You can check your file system type if you dont know it using:

$ cat /etc/fstab

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.