I have a list of 400 folders with the following pattern:
backup_01_01_2013/
backup_01_02_2013/
backup_01_03_2013/
...
backup_08_25_2014/
A new folder is created every day via a cron job.
I want to delete all folders EXCEPT:
Keep the 30 most recent folders
Keep the first of every month
How can I delete all the unnecessary folders using Bash in Linux?
So, assuming they're all in the same directory.
I'll point out I tested portions of this script, but not all of it, so you'll probably want to do some modification/testing before you actually run it - lest you end up with all your directories removed.
# Find the date 30 days ago.
recent_dirs=`date -d "-30 days" +%d-%m-%Y`
rec_month=`echo "${recent_dirs}" | cut -d '-' -f2`
rec_day=`echo "${recent_dirs}" | cut -d '-' -f1`
rec_month=`echo "${recent_dirs}" | cut -d '-' -f3`
# Go to your "home" directory for the directories.
cd /path/to/home/directory
for i in *; do
# Check to see if the element is a directory.
if [ -d "${i}" ]; then
echo "Processing directory - ${i} ... "
# Determine the date information for the directory.
cur_month=`cat "${i}" | cut -d '_' -f1`
cur_day=`cat "${i}" | cut -d '_' -f2`
# Keep all directories from the first of the month.
if [ "${first_day}" -eq "01" ]; then continue; fi
# Keep all directories from the current month and current year.
if [ "${cur_month}" -eq "${rec_month}" ]; then
if [ "${cur_year}" -eq "${rec_year}" ]; then continue; fi
fi
# Keep all directories from last month, but newer than today's DAY. I'm not
# a pro at bash arithmetic, so you might have to goof with the subshell
# math to get it to work quite right.
if [ "${cur_month} -eq $(( expr $rec_month - 1 )) ]; then
if [ "${cur_day}" -gt "${rec_day}" ]; then continue; fi
fi
# So at this point, I think we've dealt with everything, except the case where
# the current month is January, and so you're trying to save December's
# directories from last year. I think this handles it.
if [ "${rec_month}" -eq "01" ]; then
if [ "${cur_month} -eq "12" ]; then
if [ "${cur_year}" -eq $(( expr ${rec_year} - 1 )) ]; then continue; fi
fi
fi
# If we haven't stopped processing the directory by now, it's time
# remove our directory.
rm -fr "${i}"
else
echo "Skipping non-directory "${i}"...
do
exit 1
Something this won't do is deal with months with 31 days in it, so you may end up in many cases having saved 31 directories, instead of 30. I get the impression that you're trying to do a cleanup, and not a strict compliance routine, though...
Quick & dirty - try 'ls -ltr' combined with tail -30 to get all but 30. run a for loop and rm -rf
Related
I need to control files in a folder... The script has to wait the file until it exists...
These files have the name... The format is file_d01_YYYY-MM-DD_HH:00:00. For example:
file_d01_2018-11-12_00:00:00
file_d01_2018-11-12_01:00:00
And so on, for 7 days ahead.
!/bin/bash
ZZ=`date +%k`
date=$(date +%Y%m%d)
if [[ $ZZ -ge 2 ]] && [[ $ZZ -lt 14 ]] ; then #03:45 UTC
ZZ=00
PARAM=`date +%Y%m%d`$ZZ
PARAM2=`date +%Y-%m-%d`
elif [[ $ZZ -ge 14 ]] && [[ $ZZ -lt 23 ]] ; then #15:45 UTC
ZZ=12
PARAM=`date +%Y%m%d`$ZZ
PARAM2=`date +%Y-%m-%d`
fi
rundir=/home/$PARAM/wrfv3
dir=/home/$PARAM
data=$(date +%Y-%m-%d)
data1=$(date -d "1 day" +%Y-%m-%d)
data2=$(date -d "2 day" +%Y-%m-%d)
data3=$(date -d "3 day" +%Y-%m-%d)
data4=$(date -d "4 day" +%Y-%m-%d)
data5=$(date -d "5 day" +%Y-%m-%d)
data6=$(date -d "6 day" +%Y-%m-%d)
days=( "$data" "$data1" "$data2" "$data3" "$data4" "$data5" "$data6" ) #array of days
values=( {00..23} ) #array of 24 hours
echo ${#values[#]}
# Here, using to loops, I check if files exist...for every day and hour
for day in "${days[#]}"; do
for value in "${values[#]}"; do
echo file_d01_${day}_${value}:00:00
while [ ! -f $rundir/file_d01_2018-11-15_20:00:00 ] # while file doesn't exist...wait...and repeat checking till it exists...
do
echo "waiting for the file"
sleep 10
done
echo "file exists"
sleep 5
done
done
I receive always "waiting for the file"...and they exist... where is the problema in the code?
You should add the double quotes "" to protect the path. It's a good practice. Also bash expansion escapes the : character, so maybe it is an issue in your context (not in the one i did the test).
while [ ! -e "$rundir/file_d01_2018-11-15_20:00:00" ]
I would suggest to follow those steps:
Protect the path with double quotes "" (not simple ones, otherwise $rundir won't be expanded)
Write echo "waiting for the file $rundir/file_d01_2018-11-15_20:00:00" to see what path you're testing
Additionally, use -e to see any changes (-e checks for a path existence, not only a regular file one)
Note: the brackets [ ] invokes in fact test. So, man test will give you the operators you can use and their meanings. Also nowadays bash has double brackets [[ ]] as built-in operators, more powerful, which can be used instead.
The code in the question contains:
echo file_d01_${day}_${value}:00:00
while [ ! -f $rundir/file_d01_2018-11-15_20:00:00 ]
It's calculating a file name, echoing it, and then checking for a (probably different) fixed, unchanging, file name. It should check for the calculated file name. For example:
file=file_d01_${day}_${value}:00:00
echo "$file"
while [ ! -f "$rundir/$file" ]
To make debugging easier, it would be better to have:
filepath=$rundir/file_d01_${day}_${value}:00:00
echo "$filepath"
while [ ! -f "$filepath" ]
The full code in the question has many issues (starting with a broken shebang line). It's a good idea to make Bash code Shellcheck-clean.
Directory structure
MyDirectory
-data/
-DATA-TT_20160714_soe_test_testbill_52940_1.lst
-output/
-DATA-TT_20160714_soe_test_testbill_52940_1.pdf
-Backup/
enter code here
#!/bin/bash
for i in $( ls ); do
echo $i
#cd $i
#cd $i/data/
echo $i
cd $i/data/
echo $i/data/
$(ls *1.lst)
cd ../output
$(ls *1.pdf)
done
I need to navigate in the directories and the sub directories where
the
input and output files are kept. These file have
date in YYYYMMDD format which I need to compare with current date.
If the difference is greater than 1 month I need to
zip those file and move them to Backup directory. The "DATA-TT" part
is constant.
Can anyone help me in this.There may be many directories with same sub directories structure.Example MyDirectory1,MyDirectory2,MyDirectory3
Have to leave for a meeting. I'll leave you the script I've been working on to help you:
#!/bin/sh
# in your case filename would be the variable used in the for loop
filename=$(find DATA-TT*)
# Part gets the date from the filename
part=$(echo $filename | grep -Eo '[[:digit:]]{8}')
echo "$filename -> $part"
# limit_date is current date -30 days
limit_date=$(date +'%Y%m%d' -d "now 30 days")
echo $cur_date
# this part compares and echoes, you can try it and replace echoes with ziping, moving, etc.
if [ $part -ge $limit_date ]
then
echo "part is older than 1 month"
else
echo "part had not yet reached 1 month age"
fi
This one for the data directory the same for the output
#!/bin/bash
list=($(find data -name "DATA-TT_*"))
limit=`date +%Y%m%d -d "-30 days"`
for i in ${list[#]}; do
filedate=$(echo $i| cut -d'_' -f 2)
if [ "$limit" -gt "$filedate" ]; then
mv $i backup
fi
done
What I want to do is reorganize files in my Camera Roll folder. Using the creation date I want to Put them inside folders according to Year/Month Format using their creation date.
In this answer, they explain how to make folders and organize them:
https://stackoverflow.com/a/1314394/4980886
#!/bin/bash
find $PHOTO_DIR -regextype posix-extended -type d -regex '.*/[0-9]{4}/[0-9]{2}/[0-9]{2}$' |
while read dir; do
newdir="$(echo $dir | sed 's#/\([0-9]\{4\}\)/\([0-9]\{2\}\)/\([0-9]\{2\}\)$#/\1-\2-\3#')"
mv "$dir" "$newdir"
rmdir "$(dirname $dir)"
rmdir "$(dirname $(dirname $dir))"
done
But it doesn't address how to get the creation date, maybe I should get the metadata from EXIF data. How to do either?
According to exiftool man page 'Renaming examples'
exiftool '-Directory<DateTimeOriginal' -d %Y/%m/%d "$dir"
and if only copying is required, there is an option:
exiftool -o . '-Directory<DateTimeOriginal' -d %Y/%m/%d "$dir"
has the same effect as above except files are copied instead of moved.
i have written a bash script to copy files straight off my iphone/ipad and copy them into folders on a target drive based on image creation date. i use a program called exiftool found at http://www.sno.phy.queensu.ca/~phil/exiftool/
for a given image, i extract the creation datetime into an array using
DATEBITS=( $(exiftool -CreateDate -FileModifyDate -DateTimeOriginal "$IMGFILE" | awk -F: '{ print $2 ":" $3 ":" $4 ":" $5 ":" $6 }' | sed 's/+[0-9]*//' | sort | grep -v 1970: | cut -d: -f1-6 | tr ':' ' ' | head -1) )
where $IMGFILE is the path to the image file. you can then get access to the year, month, day etc using
YR=${DATEBITS[0]}
MTH=${DATEBITS[1]}
DAY=${DATEBITS[2]}
HR=${DATEBITS[3]}
MIN=${DATEBITS[4]}
SEC=${DATEBITS[5]}
it is then trivial to create the directory you need to stash the image file in
I've been working on sorting 14,000 photos from 1997 on. It's a bear because not all are digital cameras, especially the early ones. I used the 'CreateDate' tag in the image files.
I wrote the following BASH script to perform the sorting based on EXIF data, if possible. It looks for the EXIF 'CreateDate' tag first. If found, it uses it. If not, it looks for the 1st 8 characters of the file name to see if they are a VALID date (ANDROID, etc). If neither tests positive, it looks for the EXIF 'FileModifyDate' tag, which can be inaccurate. If the EXIF 'CreateDate' is found, the date prefix (YYYMMDD-) will be added to the file name (if it doesn't already exist) and then it will be moved into it's appropriate directory. If all three tests fail, the file is left alone for user intervention.
If you're lucky, and the camera supported it, and the photographer enabled it, the date may be imprinted on the image for you. I had to sort MANY photos this way, so be sure to look at the photos that are not processed and those that use the EXIF 'FileModifyDate' method of sorting.
Also, if you find you have some of those KODAK PCD picture files, you can use ImageMajick's "convert" like so:
convert $OrigFileName[$SUFX] -colorspace RGB "$(basename $OrigFileName .pcd).jpg"
However, ImageMajick doesn't always copy all the tags to the new image file but you can use EXIFTOOL to transfer the tags to your new image file like so:
exiftool -tagsFromFile $OrigFileName $(basename $OrigFileName .pcd).jpg
Code:
#! /bin/bash
# This script is used to sort photos. It uses the EXIFTOOL to
# 1st attempt to extract the photo's "CreateDate". If it is
# invalid, then the file name is checked to see if it begins
# with "YYYYMMDD", which is also checked for validity. If the
# prior two checks fail, then the photo's "FileModifyDate" is
# used but can be inaccurate.
# If a valid creation date is found and the file name is NOT
# date-encoded, then the file is renamed with a "YYYYMMDD-"
# prefix.
#=======================================================================
# Revision index:
# 2019-0704: KSV - Created and tested.
#=======================================================================
DEBUG=0 # Debugging
DRYRUN=0 # Do everything but move the files
NOTE="" # Notes
# ANSI COLORS
CRE="$(echo -e '\r\033[K')"
RED="$(echo -e '\033[1;31m')"
GRN="$(echo -e '\033[1;32m')"
YEL="$(echo -e '\033[1;33m')"
BLU="$(echo -e '\033[1;34m')"
MAG="$(echo -e '\033[1;35m')"
CYN="$(echo -e '\033[1;36m')"
WHT="$(echo -e '\033[1;37m')"
NML="$(echo -e '\033[0;39m')"
#=======================================================================
# Functions
#=======================================================================
# Enter with: YEAR, MONTH and DAY
# Returns: 0=invalid date, 1=valid date
# EX: IsValidDate $YEAR $MONTH $DAY
IsValidDate() {
#echo "Parm: Y=$1,${#1} M=$2,${#2} D=$3,${#3}" >/dev/stderr
if ([ "$1" -ge "1950" ] && [ "$1" -le "2050" ]) || \
([ "$2" -ge "01" ] && [ "$2" -le "12" ]) || \
([ "$3" -ge "01" ] && [ "$3" -le "31" ]) ; then
echo "1" # valid date
else
echo "0" # invalid date
fi
}
# Dump debugging info
# EX: $(DumpDebug $FN $FILE $EXT $FN_WD $DATE $YEAR $MONTH $DAY "$NOTE")
DumpDebug() {
#echo "1=${#FN}, 2=${#FILE}, 3=${#EXT}, 4=${#FN_WD}, 5=${#DATE}, 6=${#YEAR}, 7=${#MONTH}, 8=${#DAY}, 9=${#NOTE}" >/dev/stderr
echo "================================"
echo "FN = $1"
echo "FILE = $2"
echo "EXT = $3"
echo "FN_WD = $4"
echo "DATE = $5"
echo "YEAR = $6"
echo "MONTH = $7"
echo "DAY = $8"
echo "ValidDate = $(IsValidDate $6 $7 $8)"
echo "NOTE = $9"
echo "================================"
}
#=======================================================================
# Script starts here
#=======================================================================
# Use exiftool to find video and photos
#exiftool -filename *.[JjGg][PpIi][GgFf] *.[Jj][Pp][Ee][Gg] *.[Mm][PpOo][Gg4Vv] 2>/dev/null | awk {'print $4'} | \
find . -maxdepth 1 -type f -iname "*.[JjGg][PpIi][GgFf]" -or \
-iname "*.[Jj][Pp][Ee][Gg]" -or \
-iname "*.[Mm][PpOo][Gg4Vv]" | \
while read FN ; do
FN=$(basename $FN) # strip the leading "./"
if [ -e $FN ] && [ ${#FN} != 0 ] ; then # be sure the file exists!
EXT=${FN##*.} # extract the extension
FILE=${FN%.*} # extract the base file name
# First attempt to see if there is a valid date prefix in the file name.
YEAR=$(echo ${FN:0:4} | egrep -E ^[0-9]+$ ) # insure digits only
MONTH=$(echo ${FN:4:2} | egrep -E ^[0-9]+$ ) # insure digits only
DAY=$(echo ${FN:6:2} | egrep -E ^[0-9]+$ ) # insure digits only
DATE="$YEAR:$MONTH:$DAY" # create a DATE string
# Check the filename's derived date from for validity (not NULL strings)
# and that the date falls within the proper range
if ([ ! -z "${YEAR}" ] && [ ! -z "${MONTH}" ] && [ ! -z "${DAY}" ]) && \
[ $(IsValidDate $YEAR $MONTH $DAY) == 1 ] ; then
if [ $DEBUG == 1 ] ; then echo "ValidDate: $(IsValidDate $YEAR $MONTH $DAY)" ; fi
FN_WD=0 # date prefix exists, do not append the derived date to the filename.
else
FN_WD=1 # append the derived date prefix to the filename.
fi
# Next, attempt to find an EXIF CreateDate from the file, if it exists.
DATE=$(exiftool -s -f -CreateDate $FN | awk '{print $3}')
# Perform sanity check on correctly extracted EXIF CreateDate
if [ "${DATE}" != "-" ] && [ "${DATE}" != "0000:00:00" ] ; then
# Good date extracted, so extract the year, month and day
# of month from the EXIF info
echo "A valid ${WHT}CreateDate${NML} was found, using it."
YEAR=${DATE:0:4}
MONTH=${DATE:5:2}
DAY=${DATE:8:2}
NOTE="(by CreateDate)"
else
# EXIF CreateDate invalid or not found, so attempt to derive the
# date from the file name.
YEAR=$(echo ${FN:0:4} | egrep -E ^[0-9]+$ ) # insure digits only
MONTH=$(echo ${FN:4:2} | egrep -E ^[0-9]+$ ) # insure digits only
DAY=$(echo ${FN:6:2} | egrep -E ^[0-9]+$ ) # insure digits only
DATE="$YEAR:$MONTH:$DAY" # create a DATE string
# check the extracted date from filename for validity (not NULL strings)
# and that the date falls within the proper range
#if [ -z "${YEAR}" ] || [ -z "${MONTH}" ] || [ -z "${DAY}" ] ; then
if ([ ! -z "${YEAR}" ] && [ ! -z "${MONTH}" ] && [ ! -z "${DAY}" ]) && \
[ $(IsValidDate $YEAR $MONTH $DAY) == 1 ] ; then
echo "A valid ${WHT}FileNameDate${NML} was found, using it."
NOTE="(by file name)"
else
# EXIF CreateDate and FileNameDate extraction failed, so attempt
# to extract the EXIF FileModifyDate from the file, if it exists.
DATE=$(exiftool -s -f -FileModifyDate $FN | awk '{print $3}')
# Perform sanity check on correctly extracted EXIF FileModifyDate
if [ "${DATE}" != "-" ] && [ "${DATE}" != "0000:00:00" ] ; then
# Good FileModifyDate found, extract the year, month and
# day of month from the EXIF info
echo "A valid EXIF CreateDate and FileNameDate were not found!"
echo " The innacurate ${WHT}FileModifyDate${NML} will be used."
YEAR=${DATE:0:4}
MONTH=${DATE:5:2}
DAY=${DATE:8:2}
NOTE="(!inaccurate! by FileModifyDate)"
FN_WD=0 # date prefix exists, do not append the derived date to the filename.
else
echo "Invalid date retrieved!"
if [ $DEBUG == 1 ] ; then
echo "Length = ${#YEAR}-${#MONTH}-${#DAY}"
fi
echo "Skipping File: $FN..."
echo
fi
fi
fi
# Modify the filename if a valid EXIF CreateDate or FileNameDate was found.
if [ $FN_WD == 0 ] ; then
FILE=${FILE}.${EXT}
else
FILE=${YEAR}${MONTH}${DAY}-${FILE}.${EXT}
fi
# Debug output
if [ $DEBUG == 1 ] ; then DumpDebug $FN $FILE $EXT $FN_WD $DATE $YEAR $MONTH $DAY "$NOTE" ; fi
# We have a date, hopefully a good one, move the file
if [ $DRYRUN == 0 ] ; then
# create the directory structure. Pipe errors to NULL
mkdir -p $YEAR/$MONTH/$DAY >/dev/null 2>&1
# move the file to the appropriate directory
echo " -> Moving $FN to $YEAR/$MONTH/$DAY/$FILE $NOTE"
mv $FN $YEAR/$MONTH/$DAY/$FILE
echo
else
echo "Dryrun: Moving $FN to $YEAR/$MONTH/$DAY/$FILE"
echo
fi
# Clear the variables
FN=""; FILE=""; EXT=""; FN_WD=""; DATE=""; YEAR=""; MONTH=""; DAY=""; NOTE=""
else
echo
echo "File $FN not found!"
echo
fi
done
have been banging my head around the same or similar problem.
Exiftool is a powerful thing, however it has some limitations and it doesn't really solve file duplicate problem.
This is what I use in my script
# EXIFSubSecCreateDateParser extracts EXIF metadata: the year, month, day, hour, minute, second, subsecond,
# and generates date and note
EXIFSubSecCreateDateParser() {
# Define a variable and pass the arguments
EXIF_OUTPUT="${1}"
# Substitute dots with a common colon delimiter
EXIF_OUTPUT_SUBSTITUTE="${EXIF_OUTPUT//./:}"
# Define delimiter
DELIMITER=":"
# Concatenate the delimiter with the main string
DELIMITED_EXIF_OUTPUT="${EXIF_OUTPUT_SUBSTITUTE}${DELIMITER}"
# Split the text based on the delimiter
EXIF_OUTPUT_ARRAY=()
while [[ "${DELIMITED_EXIF_OUTPUT}" ]]; do
EXIF_OUTPUT_ARRAY+=( "${DELIMITED_EXIF_OUTPUT%%${DELIMITER}*}" )
DELIMITED_EXIF_OUTPUT="${DELIMITED_EXIF_OUTPUT#*${DELIMITER}}"
done
# Assign the array values to the corresponding variables
YEAR="${EXIF_OUTPUT_ARRAY[0]}"
MONTH="${EXIF_OUTPUT_ARRAY[1]}"
DAY="${EXIF_OUTPUT_ARRAY[2]}"
HOUR="${EXIF_OUTPUT_ARRAY[3]}"
MINUTE="${EXIF_OUTPUT_ARRAY[4]}"
SECOND="${EXIF_OUTPUT_ARRAY[5]}"
SUBSECOND="${EXIF_OUTPUT_ARRAY[6]}"
DATE="${YEAR}:${MONTH}:${DAY}"
}
# Attempting to extract EXIF metadata from the file to an array.
EXIF_EXTRACT=( $(exiftool -s -f -SubSecCreateDate -CreateDate -Model "${WIPSortedFileAbsolutePath}" | awk '{print $3":"$4}') )
# Assigning the array values to variables
EXIF_SubSecCreateDate_OUTPUT="${EXIF_EXTRACT[0]}"
EXIF_CreateDate_OUTPUT="${EXIF_EXTRACT[1]}"
EXIF_Model_OUTPUT="${EXIF_EXTRACT[2]}"
# Setting Target Directory structure with TargetDirectoryStructure
DestinationStructure="${YEAR}/${MONTH}/${DAY}"
# Setting Filename format
FormatedFileName="${MODEL}-${YEAR}${MONTH}${DAY}-${HOUR}${MINUTE}${SECOND}-${SUBSECOND}.${NormalisedFileExtension}"
# Moving the file to the Desination File Path
mv "${File}" "${DestinationPath}/${DestinationStructure}/${FormatedFileName}"
I found some answers but piecemeal solutions did not go far enough. I ended up writing my own thing with a kick-start based off Johnny Quest's script.
Anyway, have a look at https://github.com/ivang-coder/Neatly-Sorted
It might give you some ideas for your endeavor.
I'm really struggling to see why this while-loop never ends, when the loop starts, my variable LOC is set to Testing/, which is a directory I created to test this program, it has the following layout:
I want the loop to end once all Directories have had the "count" function applied to them.
Here are the things I have tried;
I've checked my count function, and it doesn't produce an infinite loop
I've tried running through the algorithm by hand
PARSE=1
LOC=$LOC/
count
AVAILABLEDIR=$(ls $LOC -AFl | sed "1 d" | grep "/$" | awk '{ print $9 }')
while [ $PARSE = "1" ]
do
if [[ ${AVAILABLEDIR[#]} == '' ]]; then
PARSE=0
fi
DIRBASE=$LOC
for a in ${AVAILABLEDIR[#]}; do
LOC="${DIRBASE}${a}"
LOCLIST="$LOCLIST $LOC"
count
done
for a in ${LOCLIST[#]}; do
TMPAVAILABLEDIR=$(ls $a -AFl | sed "1 d" | grep "/$" | awk '{ print $9 }')
PREPEND=$a
if [[ ${TMPAVAILABLEDIR[#]} == '' ]]; then
continue
fi
for a in ${TMPAVAILABLEDIR[#]}; do
TMPAVAILABLEDIR2="$TMPAVAILABLEDIR2 ${PREPEND[#]}${a}"
done
NEWAVAILABLEDIR="$NEWAVAILABLEDIR $TMPAVAILABLEDIR2"
done
AVAILABLEDIR=$NEWAVAILABLEDIR
NEWAVAILABLEDIR=''
LOC=''
done
I am really struggling, and any input would be greatly appreciated, I've been trying to figure this out for the last couple of hours.
You should try to run the script with argument -x, or write it into the first line:
#!/bin/bash -x
Then it tells you everything it does.
In that case, you might notice two errors:
You never reset TMPAVAILABLEDIR2
You do ls on regular files as well.
If you really must avoid recursion, try this. It completely recursion-free:
#!/bin/bash
count() {
echo counting "$1"
}
todo=(Testing)
while test ${#todo[#]} != 0
do
doit=("${todo[#]}")
todo=()
for dir in "${doit[#]}"
do
for entry in "$dir"/* # If the directory is empty, this shows an entry named "*"
do
test -e "$entry" || continue # Skip the entry "*" of an empty directory
count "$entry"
test -d "$entry" || continue
todo+=("$entry")
done
done
done
You wrote you want to perform "count" on all directories.
Look at the options of find:
find $LOC -type d | while read dir; do
cd $LOC
cd ${dir}
count
done
Or shorter (when your function count accepts a directory as parameter 1):
find $LOC -type d | xargs count
I now see you do not want to use find or ls -R (recursive function). Then you should make your own recursive function, something like
function parseDir {
ls -d */ $1 | while read dir; do
count
parseDir $1/$dir
done
}
I have no idea if this will work, but it’s an interesting question I couldn't stop thinking about.
while true ; do
for word in "$(echo *)" ; do
if [[ -d "$word" ]] ; then
d[$((i++))]="$PWD"/"$word"
elif [[ -f "$word" ]] ;then
f[$((j++))]="$PWD"/"$word"
fi
done
[[ $k -gt $i ]] && cd ..
cd "$d[$((k++))]" || break
done
I have a directory full of log files that I need to rotate using a posix shell script on an embedded system. They are named file, file.0, file.1 and so on. I didn't see this question already asked and had trouble finding it on google.
I ended up solving this myself, and thought I should post the solution here. If anyone has suggestions for improvement, feel free to add them.
# Usage: rotate_logs base [max]
# Example:
# rotate_logs messages 10 # Rotate "messages" files keeping only 10 rotated files.
rotate_logs() {
#set -x
local base="$1"
# ensure we have a base and it is not null
if [ $# -lt 1 -o -z "$1" ]; then
echo "Usage: $0 base [max]" >&2
echo "Example:" >&2
echo -e "\t$0 messages 10\t# Rotate \"messages\" files keeping only 10 rotated files." >&2
return 1
fi
# see if we were given a max number and make sure it is a number
if [ $# -ge 2 ]; then
if ! echo "$2" | egrep -q '^[0-9]+$'; then
echo "Maximum number, \"$2\", must be a number." >&2
return 1
fi
local max=$2
fi
local i
local n
# Get a list of all of the already rotated files in reverse
# base.3 base.2 base.1
for i in $(ls -1r "$base".*); do
# Calculate the next number for the current file, i.e. 4 for base.3
n=$((1 + $(echo $i | sed 's,'"$base"'.,,')))
# If the new file number is greater than max, delete it.
if [ $n -gt ${max:-999999} ]; then
rm -rf "$i"
else
# otherwise move the file to the new number
mv $i "$base".$n
fi
done
# If there is a "base" file with no extension move that now.
if [ -e "$base" ]; then
mv "$base" "$base".0
fi
}