Expand bash functions in parameter find exec

How can I make find

my shell set functions and aliases apply inside its exec parameter?

For example, I defined a function similar to bzip2 , but using 7z :

function 7zip () {for f in $ @ ; do ls -alF "$ f"; 7za a -t7z -m0 = lzma -mx = 9 -mfb = 64-md = 64m -ms = on "$ f.7z" "$ f" && & & touch -r "$ f" "$ f.7z" && & & rm -fv "$ f" && & ls -alF "$ f.7z"; made; }

When I push files longer than 7 days to compress:

find . -mtime +7  -name "G*.html"   -execdir  7zip {}  + 


Instead of extending 7zip , no error command was found.

It's all inside a shell script.


source to share

4 answers

All four commands work fine with function calls. Adjust your search parameters as needed. They all handle spaces in filenames. Personally, I see no point in bypassing another bash instance, but I have included two versions that call bash.

IFS=$'\n'; f=($(find /tmp -maxdepth 1 -name "$USER.*")); f7zipi "${f[@]}"

IFS=; find /tmp -maxdepth 1 -name "$USER.*" | while read -r f ;do f7zipi "$f"; done 

IFS=$'\n'; bash -c 'IFS=; f7zipi "$@"' 0 $(find /tmp -maxdepth 1 -name "$USER.*")  

find /tmp -maxdepth 1 -name "$USER.*" -exec bash -c 'IFS=; f7zipi "$@"' 0 {} +;   


The following is how I configured this feature using GNU bash 4.1.5 on Ubuntu 10.04

BTW. You should use local f

in your function so that you don't come across a calling script variable with the same name.

This is exactly what I added to my ~ / .bashrc

function f7zipi() { 
    local f
    for f in $@; do 
        ls -alF "$f"
        7za a -si -t7z -m0=lzma -mx=9 -mfb=64 \
        -md=64m -ms=on "$f.7z" < "$f" && 
            touch -r "$f" "$f.7z" && 
            rm -fv "$f" && 
            ls -alF "$f.7z"
export -f f7zipi


When I assign the above function in bash terminal command line only, the script runs from that command line, if it calls the function ... If I still apply export -f f7zipi

to the same command line. Then the script succeeds ... However scipt only works for that specific command line session.

When function and export are included ~/bashrc

, the script runs every time in any bash session.

This is a test script

rm -fv "$f" "$f".7z
rm -fv "$g" "$g".7z
printf 'abcdefg'>"$f"
printf 'lmnopqr'>"$g"
IFS=$'\n'; f=($(find /tmp -maxdepth 1 -name "$USER.*")); f7zipi "${f[@]}"




You can export a function definition with:

export -f 7zipi


but using an indexer whose name starts with a number is asking for problems. Try changing the name to something sensible. (for example, "f7zipi" or "_7zipi")



Being an impatient coder than I am, at the moment I changed it to a few lines:

hitlist=$(find . -mtime +7  -name "G*.html")
7zipi $hitlist |awk ' !x[$0]++'


This is the awk bit at the end, by the way, so that the output only prints lines that weren't visible before, so it doesn't clutter with zillion lines:

7-Zip (A) 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,2 CPUs)
Compressing  [Content]      
Everything is Ok


NOT really the answer; I still like find to use my macros in general.



It looks like not everyone find

will accept a function as an argument for --execdir

. It didn't work for me either in original form or with help export -f


However, if you inject the script from your function it will work

find . -mtime +7 -name "G*.html" -execdir  /path/to/script_7zipi {} +




All Articles