to delete files older than 7 days using Unix - shell

Requirement:
i am having the path where the files will be present .
i need to get the path from it and delete the files older than 7 days with name as .logo or ,out0 ..
ISSUE:tried the below but its going to many paths that were not listed..
#reading source path from rem_logs.txt
cat rem_logs.txt | while read FILE_PATH
do
echo " Path obtained from rem_logs.txt --> '$FILE_PATH'"
echo "File has to be removed from '$FILE_PATH'"
#moving to the specified path above
find $FILE_PATH -type f -mtime +7 -print | while read FILE_NAME
echo "File is '$FILE_NAME'"
do
chmod 777 $FILE_NAME
echo "$FILE_NAME is received"
if [ "$FILE_NAME"=*.log0* -o "$FILE_NAME"=*.out0*]
then
echo " $FILE_PATH/$FILE_NAME" > $LOGPATH/abdul.txt
used above statement for testing in testing environment
else
echo "This file - $FILE_NAME need not be removed"
fi
done
UpdateLog_del.sh "$FILE_NAME is presently deleted from the above mentioned path"
done

Consider doing something like this:
while read FILE_PATH
do
#for each filename found
for FILE_NAME in $(find $FILE_PATH \( -name "*.log0" -o -name "*.out0" \) -type f -mtime +7 -print)
do
chmod 777 $FILE_NAME
echo "$FILE_NAME" >> $LOGPATH/abdul.txt
done
UpdateLog_del.sh "$FILE_NAME is presently deleted from the above mentioned path"
#read from rem_logs.txt which contains the paths
done < rem_logs.txt

Try this:
find /path -type f -mtime +7 -regex '$\|.*log0$\|.*out0$' -print | xargs -I '{}' -n1 rm -f {}

Related

traverse through folder and do something with specific file types

I'm working on a bash script that should go through a directory and print all files and if it hits a folder it should call it's self and do it again. I believe my problem lies with if [[ $file =~ \.yml?yaml$ ]]; when I remove the tilda it runs but not correctly if [[ $file = \.yml?yaml$ ]];
It returns "this a file isn't need -> $file" even though it's a yaml.
#!/bin/bash
print_files_and_dirs() {
for file in $1/*;
do
if [ -f "$file" ];
then
if [[ $file =~ \.yml?yaml$ ]];
then
echo "this is a yaml file! -> $file"
else
echo "this a file isn't need -> $file"
fi
else
print_files_and_dirs $file
fi
done
}
print_files_and_dirs .
Maybe you can use find to find the yaml files and do something with them.
find "$PWD" \
-type f \( -name "*.yaml" -or -name "*.yml" \) \
-exec echo found {} \;
If you only want the file name without the path, you could use printf to get the names and pipe it to xargs.
find "$PWD" \
-type f \( -name "*.yaml" -or -name "*.yml" \) \
-printf '%f\n' \
| xargs -I{} echo found {}

Count lines of code recursively, including compressed (zip) files

I use the following Bash script to count lines of code in one of my projects:
echo "--- CLIENT"
cd "/mypath/client"
# Count classes:
a=`find . -name \*.java -print | wc -l`
echo ""
echo "Number of Java classes: $a"
# Total count:
b=`find . -name \*.java -exec cat {} \; | wc -l`
echo ""
echo "Java lines: $b"
c=`find . -name \*.css -exec cat {} \; | wc -l`
echo ""
echo "CSS lines: $c"
d=`find . -name \*.json -exec cat {} \; | wc -l`
echo ""
echo "JSON lines: $d"
f=$((`find . -name \*.h -exec cat {} \; | wc -l` + `find . -name \*.m -exec cat {} \; | wc -l`))
echo ""
echo "iOS Objective-C lines: $f"
echo ""
echo "--- SERVER"
cd "/mypath/server"
# Count classes:
h=`find . -name \*.java -print | wc -l`
echo ""
echo "Number of Java classes: $h"
# Total count:
i=`find . -name \*.java -exec cat {} \; | wc -l`
echo ""
echo "Java lines: $i"
echo ""
echo "Total lines of code: $((b + c + d + e + f + i))"
cd ~
This script worked fine as long as all the source code was searchable this way. Now I have a different use case: some of the source code is still reachable with this script, and some of it is inside compressed zip files (located in various subfolders of "/mypath/client"). These zip files can contain the sources in the root or in various subfolders within them.
I suppose it's possible to adapt my script to take into account the zipped files in the count, but I don't know how to do it.
Counting Files
When you search for .xyz files, also search for .zip files and search their file list.
You can list all filenames in a zip archive using zipinfo archive.zip. zipinfo also supports wildcards to print only matching filenames. For instance, zipinfo archive.zip '*.java' prints only filenames ending with .java.
find . -name \*.java -print \
-o -name \*.zip -exec zipinfo -1 {} '*.java' \; |
wc -l
This command assumes that filenames do not contain linebreaks.
Counting Lines
You can print zipped files without explicitly extracting them using unzip -p archive.zip file1 file2 .... This command also accepts wildcards.
By the way: You can drastically simplify your script by using a function, since find . -name \*.xyz -exec cat {} \; | wc -l is often the same, except for xyz. Also, -exec cat {} + is way faster than -exec cat {} \;.
#! /bin/bash
countLines() {
local ext=$1
find . -name "*.$ext" -exec cat {} + \
-o -name \*.zip -exec unzip -p {} "*.$ext" \; |
wc -l
}
for ext in java css json; do
echo "$ext lines: $(countLines "$ext")"
done
unzip -p archive.zip '*.java' may print the warning caution: filename not matched: *.java if there are no .java files. You can suppress this by adding 2> /dev/null after the find command.
Keep in mind that this approach is very inefficient. find has to run for each file extension. And the zip files are read multiple times too. It would be faster to filter out all files that you want to inspect first, then run wc -l on all of them, and then sum up their line counts.

Bash - file path can not be read for LAME encoder

How do I properly escape the path to come out of find to a new command argument?
#!/bin/bash
for f in $(find . -type f -name '*.flac')
do
if flac -cd "$f" | lame -bh 320 - "${f%.*}".mp3; then
rm -f "$f"
echo "removed $f"
fi
done
returns
lame: excess arg Island of the Gods - 3.mp3
Using a Bash for loop is not ideal for the results of find or ls. There are other ways to do it.
You may want to use -print0 and xargs to avoid word splitting issues.
$ find [path] -type f -name *.flac -print0 | xargs -0 [command line {xargs puts in fn}]
Or use -exec primary in find:
$ find [path] -type f -name *.flac -exec [process {find puts in fn}] \;
Alternative, you can use a while loop:
find [path] -type f -name *.flac | while IFS= read -r fn; do # fn not quoted here...
echo "$fn" # QUOTE fn here!
# body of your loop
done

Rename files with a suffix with name of its folder

Each folder has a .mkv or .avi file.
E.g:
Sommerferien201308/eins.avi
Sommerferien201309/eins.mkv
Herbst201401/film.avi
Herbst201402/krz.mkv
Renaming to:
Sommerferien201308/Sommerferien201308.avi
Sommerferien201309/Sommerferien201309.mkv
Herbst201401/Herbst201401.avi
Herbst201402/Herbst201402.mkv
How can I rename the filename to the name of its folder?
Of course every foldername is unique. And too much to do it manually for each file/folder.
I Would try with find.
find . -type d -name "" -exec cd "" && mv {} \;
But i dont know how to select the folder name and how to make the .avi or .mkv selection and how to store the selected folder name..
You can use this find command from base folder of your folders that contain *.avi and *.mkv files:
while IFS= read -rd '' f; do
(
IFS=/
arr=($f)
if [[ $f != *"/${arr[len-2]}"* ]]; then
len=${#arr[#]}
ext="${arr[len-1]##*.}"
cd "$(dirname "$f")" && echo mv "${arr[len-1]}" "${arr[len-2]}.$ext"
fi
)
done < <(find . \( -name '*.mkv' -o -name '*.avi' \) -print0)
When you're satisfied with the output remove echo before mv.

Bash script, match on dates like?

I'm writing a script to remove some build artifacts older than 1 week.
The files have names in the form artifact-1.1-200810391018.exe.
How do I go about removing only the files that are greater than 1 week old, excluding the time in hours and minutes at the end of the date-time-stamp?
Currently it is removing all of the files in the directory.
#!/bin/sh
NIGHTLY_LOCATIONS=( "/foo" "/bar" )
ARTIFACT_PREFIX="artifact-*-"
NUM_TO_KEEP=7
for home in $(seq 0 $((${#NIGHTLY_LOCATIONS[#]} - 1))); do
echo "Removing artifacts for" ${NIGHTLY_LOCATIONS[$location]}
for file in `find ${NIGHTLY_LOCATIONS[$location]} -name "$ARTIFACT_PREFIX*"`; do
keep=true
for day in $(seq 0 $((${NUM_TO_KEEP} - 1))); do
date=`date --date="$day days ago" +%Y%m%d`
echo $(basename $file ".exe") " = " $ARTIFACT_PREFIX$date
if [ "$(basename $file ".exe")" != "$ARTIFACT_PREFIX$date" ]; then
keep=false
fi
done
if [ !$keep ]; then
echo "Removing file"
rm -f $file
fi
done done
You mean, something along the line of:
find /path/to/files -name "artifact*" -type f -mtime +7 -exec rm {} \;
?
If you trust the mtime of the file, you can do it in a simple sweep with find:
find "${NIGHTLY_LOCATIONS}" -name $ARTIFACT_PREFIX -type f -mtime +7 -delete

Resources