简体   繁体   中英

Shell Scripting:copy any missing files in a sub directory

A givenFolder will have subfolders. Each subfolder should have 36 files with following pattern: <subfoldername>_<xx>.png (eg abc_09.png, abc_10.png etc.) If any of the 36 files (01 to 36) is missing then create it in that folder by copying 1x1.png as that file, eg If abc_01.png is missing then copy 1x1.png as abc_01.png in that subfolder such that at the end each subfolder should have all 36 numbered files. Assume a hardcoded location for 1x1.png.

So far I am able to do this:

#!/bin/bash

#list all sub directories and files under it
if [ ! -z "$1" ] 
  then
    echo "Arguments passed";
    if [ -d "$1" ]
    then    
        tree -if --noreport "$1";
    else        
        echo "Supplied argument is not a directory";
    fi
else
    echo "No arguments passed";
fi

But I dont know how to go forward.

DEFAULT_PNG='/path/to/your/1x1.png'

if [[ $1 ]]; then
    echo "Arguments passed";

    if [[ -d $1 ]]; then    

        for curFile in "$1/"abc_{01..36}.png; do
            if ! [[ -f $curFile ]]; then
                cp -- "$DEFAULT_PNG" "$curFile"
            fi
        done

    else        
        echo 'Supplied argument is not a directory';
    fi
else
    echo 'No arguments passed';
fi

Read about bash brace expansion

After you have edited your question I start to understand that you want something different... So, if I got it right this time, here is a script that works for subfolders

DEFAULT_PNG='/path/to/your/1x1.png'

if [[ $1 ]]; then
    echo "Arguments passed";
    if [[ -d $1 ]]; then

        for curSubdir in "$1/"*; do 
            if [[ -d $curSubdir ]]; then #skip regular files
                dirBasename=$(basename -- "$curSubdir")
                for curFile in "$curSubdir/$dirBasename"_{01..36}.png; do
                    if ! [[ -f $curFile ]]; then
                        cp -- "$DEFAULT_PNG" "$curFile"
                    fi
                done

            fi
        done

    else        
        echo 'Supplied argument is not a directory'
    fi
else
    echo 'No arguments passed'
fi

I know a good answer has already been accepted, but my initial reading of the question took it to mean that the subfolders of givenFolder might extend down to a more arbitrary depth, and that the immediate arguments to the script (the "givenFolder"s) were not to be populated with PNG files. So here's what that might look like.

And a nod to @Aleks-Daniel for reminding me to use bash's nifty brace expansion.

#!/bin/bash

[ $# -ge 1 ] || exit 0

DEF_PNG='/tmp/1x1.png'

[ -f "$DEF_PNG" ] || ppmmake black 1 1 | pnmtopng > "$DEF_PNG" || exit 1

function handle_subdir() {
  [ -d "$1" ] || return

  local base=$(basename "$1")
  local png

  for png in "$1"/"$base"_{01..36}.png; do
    [ -e "$png" ] || cp "$DEF_PNG" "$png"
  done
}

# Only process subdirectories of the directory arguments to
# the script, but do so to an arbitray depth.
#
find "$@" -type d -mindepth 1 | while read dir; do handle_subdir "$dir"; done

exit $?

If the sub-folders are created by an opponent and include \\n characters, piping find output into bash's read command will create bad behavior. A quick test showed it to properly handle other special characters in folder/directory names (whitespace, $, *, etc), however.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM