Skip to main content
Change comment wording
Source Link
mcp
  • 857
  • 1
  • 7
  • 19

I made a modular bash function for this, based on a compilation of findings:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "$pattern"`)
    done

    # uniqfilter -dfor onlyduplicates neededonly ifwhen more than one arg, otherwise rm all files inpattern listprovided
    if (($# > 1))
    then
        printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
    else
        printf "%s\n" ${files[@]} | xargs rm
    fi
}

It is designed to work with multiple pattern arguments:

rmexcept '*.tex' '*.pdf'

NOTE: The single quotes are necessary! Otherwise bash will expand the wildcard and you will have a number of inputs equal to the matching expansion, which causes every file to eventually repeat, and thus, causes the function to delete everything!

If you don't want to remember this dangerous caveat (I don't), define rmexcept as follows:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "*$pattern"`)
    done

    # uniqfilter -dfor onlyduplicates neededonly ifwhen more than one arg, otherwise rm all files inpattern listprovided
    if (($# > 1))
    then
        printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
    else
        printf "%s\n" ${files[@]} | xargs rm
    fi
}

And use without wildcards:

rmexcept .tex .pdf

NOTE: You can still make a dangerous mistake by using a prefix *. I'll keep thinking about how to improve this.


The way I put the find results in an array might not be best practice. See this thread for more details.

I made a modular bash function for this, based on a compilation of findings:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "$pattern"`)
    done

    # uniq -d only needed if more than one arg, otherwise rm all files in list
    if (($# > 1))
    then
        printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
    else
        printf "%s\n" ${files[@]} | xargs rm
    fi
}

It is designed to work with multiple pattern arguments:

rmexcept '*.tex' '*.pdf'

NOTE: The single quotes are necessary! Otherwise bash will expand the wildcard and you will have a number of inputs equal to the matching expansion, which causes every file to eventually repeat, and thus, causes the function to delete everything!

If you don't want to remember this dangerous caveat (I don't), define rmexcept as follows:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "*$pattern"`)
    done

    # uniq -d only needed if more than one arg, otherwise rm all files in list
    if (($# > 1))
    then
        printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
    else
        printf "%s\n" ${files[@]} | xargs rm
    fi
}

And use without wildcards:

rmexcept .tex .pdf

NOTE: You can still make a dangerous mistake by using a prefix *. I'll keep thinking about how to improve this.


The way I put the find results in an array might not be best practice. See this thread for more details.

I made a modular bash function for this, based on a compilation of findings:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "$pattern"`)
    done

    # filter for duplicates only when more than one pattern provided
    if (($# > 1))
    then
        printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
    else
        printf "%s\n" ${files[@]} | xargs rm
    fi
}

It is designed to work with multiple pattern arguments:

rmexcept '*.tex' '*.pdf'

NOTE: The single quotes are necessary! Otherwise bash will expand the wildcard and you will have a number of inputs equal to the matching expansion, which causes every file to eventually repeat, and thus, causes the function to delete everything!

If you don't want to remember this dangerous caveat (I don't), define rmexcept as follows:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "*$pattern"`)
    done

    # filter for duplicates only when more than one pattern provided
    if (($# > 1))
    then
        printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
    else
        printf "%s\n" ${files[@]} | xargs rm
    fi
}

And use without wildcards:

rmexcept .tex .pdf

NOTE: You can still make a dangerous mistake by using a prefix *. I'll keep thinking about how to improve this.


The way I put the find results in an array might not be best practice. See this thread for more details.

Fix function to work with single arguments, no duplicates
Source Link
mcp
  • 857
  • 1
  • 7
  • 19

I made a modular bash function for this, based on a compilation of findings:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "$pattern"`)
    done

    # uniq -d only needed if more than one arg, otherwise rm all files in list
    if (($# > 1))
    then
        printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
    else
        printf "%s\n" ${files[@]} | xargs rm
    fi
}

It is designed to work with multiple pattern arguments:

rmexcept '*.tex' '*.pdf'

NOTE: The single quotes are necessary! Otherwise bash will expand the wildcard and you will have a number of inputs equal to the matching expansion, which causes every file to eventually repeat, and thus, causes the function to delete everything!

If you don't want to remember this dangerous caveat (I don't), define rmexcept as follows:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "*$pattern"`)
    done

    # uniq -d only needed if more than one arg, otherwise rm all files in list
    if (($# > 1))
    then
        printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
    else
        printf "%s\n" ${files[@]} | xargs rm
    fi
}

And use without wildcards:

rmexcept .tex .pdf

NOTE: You can still make a dangerous mistake by using a prefix *. I'll keep thinking about how to improve this.


The way I put the find results in an array might not be best practice. See this thread for more details.

I made a modular bash function for this, based on a compilation of findings:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "$pattern"`)
    done

    printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
}

It is designed to work with multiple pattern arguments:

rmexcept '*.tex' '*.pdf'

NOTE: The single quotes are necessary! Otherwise bash will expand the wildcard and you will have a number of inputs equal to the matching expansion, which causes every file to eventually repeat, and thus, causes the function to delete everything!

If you don't want to remember this dangerous caveat (I don't), define rmexcept as follows:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "*$pattern"`)
    done

    printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
}

And use without wildcards:

rmexcept .tex .pdf

NOTE: You can still make a dangerous mistake by using a prefix *. I'll keep thinking about how to improve this.


The way I put the find results in an array might not be best practice. See this thread for more details.

I made a modular bash function for this, based on a compilation of findings:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "$pattern"`)
    done

    # uniq -d only needed if more than one arg, otherwise rm all files in list
    if (($# > 1))
    then
        printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
    else
        printf "%s\n" ${files[@]} | xargs rm
    fi
}

It is designed to work with multiple pattern arguments:

rmexcept '*.tex' '*.pdf'

NOTE: The single quotes are necessary! Otherwise bash will expand the wildcard and you will have a number of inputs equal to the matching expansion, which causes every file to eventually repeat, and thus, causes the function to delete everything!

If you don't want to remember this dangerous caveat (I don't), define rmexcept as follows:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "*$pattern"`)
    done

    # uniq -d only needed if more than one arg, otherwise rm all files in list
    if (($# > 1))
    then
        printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
    else
        printf "%s\n" ${files[@]} | xargs rm
    fi
}

And use without wildcards:

rmexcept .tex .pdf

NOTE: You can still make a dangerous mistake by using a prefix *. I'll keep thinking about how to improve this.


The way I put the find results in an array might not be best practice. See this thread for more details.

Add maxdepth so directories are not emptied
Source Link
mcp
  • 857
  • 1
  • 7
  • 19

I made a modular bash function for this, based on a compilation of findings:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "$pattern"`)
    done

    printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
}

It is designed to work with multiple pattern arguments:

rmexcept '*.tex' '*.pdf'

NOTE: The single quotes are necessary! Otherwise bash will expand the wildcard and you will have a number of inputs equal to the matching expansion, which causes every file to eventually repeat, and thus, causes the function to delete everything!

If you don't want to remember this dangerous caveat (I don't), define rmexcept with this versionas follows:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "*$pattern"`)
    done

    printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
}

And use without wildcards:

rmexcept .tex .pdf

NOTE: You can still make a dangerous mistake by using a prefix *. I'll keep thinking about how to improve this.


The way I put the find results in an array might not be best practice. See this thread for more details.

I made a modular bash function for this, based on a compilation of findings:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -type f -not -iname "$pattern"`)
    done

    printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
}

It is designed to work with multiple pattern arguments:

rmexcept '*.tex' '*.pdf'

NOTE: The single quotes are necessary! Otherwise bash will expand the wildcard and you will have a number of inputs equal to the matching expansion, which causes every file to eventually repeat, and thus, causes the function to delete everything!

If you don't want to remember this dangerous caveat (I don't), define rmexcept with this version:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -type f -not -iname "*$pattern"`)
    done

    printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
}

And use without wildcards:

rmexcept .tex .pdf

NOTE: You can still make a dangerous mistake by using a prefix *. I'll keep thinking about how to improve this.


The way I put the find results in an array might not be best practice. See this thread for more details.

I made a modular bash function for this, based on a compilation of findings:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "$pattern"`)
    done

    printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
}

It is designed to work with multiple pattern arguments:

rmexcept '*.tex' '*.pdf'

NOTE: The single quotes are necessary! Otherwise bash will expand the wildcard and you will have a number of inputs equal to the matching expansion, which causes every file to eventually repeat, and thus, causes the function to delete everything!

If you don't want to remember this dangerous caveat (I don't), define rmexcept as follows:

rmexcept()
{
    files=()
    for pattern in "$@"
    do
        files+=(`find . -maxdepth 1 -type f -not -iname "*$pattern"`)
    done

    printf "%s\n" ${files[@]} | sort | uniq -d | xargs rm
}

And use without wildcards:

rmexcept .tex .pdf

NOTE: You can still make a dangerous mistake by using a prefix *. I'll keep thinking about how to improve this.


The way I put the find results in an array might not be best practice. See this thread for more details.

Fix grammar
Source Link
mcp
  • 857
  • 1
  • 7
  • 19
Loading
Function not alias; highlight find
Source Link
mcp
  • 857
  • 1
  • 7
  • 19
Loading
Source Link
mcp
  • 857
  • 1
  • 7
  • 19
Loading