0

Based on this question,

How to delete directories based on `find` output?

I tried to remove only the first folder of result doing:

find * -type d | head -n1 | -exec rm -rf {} \;

But I receive this error:

bash: -exec: command not found

What's wrong?

2
  • -exec is a flag to find the | is a "pipe" between commands that connects the output of one command to the input of the next. So after the pipe is a separate command. Jan 21 '19 at 13:51
  • Similar recent confusion: unix.stackexchange.com/q/495361/117549
    – Jeff Schaller
    Jan 21 '19 at 13:58
4

You can use -quit after using -delete or -exec:

-quit
Exit immediately. No child processes will be left running, but no more paths specified on the command line will be processed.


Deleting the first result of your find command:

find * -type d -exec rm -Rf {} \; -quit

or

find . ! -path . -type d -exec rm -Rf {} \; -quit

The latter will find hidden folders.


Note, that your find output may not be sorted alphabetically.

For deletion of first result afer sorting:

find * -maxdepth 1 -type d -print0 | sort -z | head -zn1 | xargs -r0 rm -Rf

For numeric sort, use sort -zn.

1
  • Thanks a lot! so I'll add "sort -z", but I'll have the same problem of | head -n1, isn't it? Jan 21 '19 at 14:33
0

pLumo has adequately given a few good alternative solutions in their answer. I'm providing a totally different approach.

You will notice that the find command, the way you're using it with * describing the top-level search paths, is only really used for finding the first directory among the names that * expands to.

You may do this with a shell loop too, which results in code that is easier to read and to see what it does:

shopt -s dotglob nullglob

for name in *; do
    if [ -d "$name" ] && [ ! -h "$name" ]; then
        rm -rf -- "$name"
        break
    fi
done

This loop, which assumes it's running in a bash shell, iterates over all names matched by * (including hidden names). The body of the loop tests whether the current name is a directory (without being a symbolic link to a directory), and if so deletes the directory recursively before exiting the loop.

A similar effect could be had in the zsh shell with the much simpler command

rm -rf -- *(D/[1])

This removes the first directory that * expands to. The globbing qualifier (D/[1]) restricts the match of * to only directories (/), but includes hidden names (D), and returns only the first matching name ([1]). If there are no directories in the current directory, you would get a "no matches found" error message from the shell.

-1

This seems very dangerous but you could try:

find * -type d | head -n1 | xargs rm -rf
1
  • 1
    Indeed dangerous. Having>$ ls: important_file important_file\nfake_folder, your command will delete very_important_file. Better use find -print0 and head -z and xargs -0.
    – pLumo
    Jan 21 '19 at 14:06
-1

for me worked this code:

  • finds ONLY the files with -type f,
  • filter files not containing ".gz"
  • select N files in this case ONLY FIRST ONE -n 1

code:

find . -type f ! -name "*.gz" | head -n 1 | xargs rm -rf {} ;

1
  • 1
    This seems to solve a different problem. Note that the user uses * as the search path. This means their find command will never (or should never) recurse into directories.
    – Kusalananda
    Jul 5 at 10:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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