How to find file extension using UNIX? - unix

I need to find file extension for file to be processed using UNIX. The two file extension which i will be handling are '.dat' and '.csv'.
Please let me know how this can be done.

find . -name "*.dat" -o -name "*.csv"
Finds in the current directory and recursively down, all files that end in those two extensions.

So my stab at this.
filename=file.dat
extension=$(echo ${filename}|awk -F\. '{print $2}')
if [ ${extension} == "dat" ]; then
your code here
fi
Echo the variable ${filename} pipe that output to awk. With awk reset the field separator to a . then pick up field 2 (the print $2 part)

This is what you want ?
find . -name "*.dat"
find . -name "*.csv"

find /path -type f \( -name "*.dat" -o -name "*.csv" \) | while read -r file
do
echo "Do something with $file"
done

if you have the filename in a variable
filename = test.csv
then just use this to get the "csv" part:
echo ${filename##*.}
works for bash, try it in ksh
edit:
filename=test.csv
fileext=${filename##*.}
if [ fileext = "csv" ]; then
echo "file is csv, do something"
else
if [ fileext = "dat" ]; then
echo "file is dat, do something"
else
echo "mhh what now?"
fi
fi

Related

Bourne - Binary operator expected

Need to check if there is a result of $found_files. However, I got an error "binary operator expected" in the 2nd line of code. Please help.
found_files=`find . -name "*.php" -printf '%f '` # find all php files in the current folder
if [ -z $found_files ] ;
then
echo "No php file found."
else
echo -e "$found_files"
fi

How to calculate total size of all css,js and html pages separately uing shell script?

I have the following code in shell script
find -name "*.css" -exec -printf '%16f Size: %6s\n'
This gives me the file size of every css file. How do I modify this to get the added sum of all the file sizes ?
You could use awk:
find . -name "*.css" -type f -printf '%s\n' | awk '{ tot+=$0 } END { print tot }'
Or in pure bash:
total=0
while read -r s;
do
total=$(( total+s ))
done < <(find . -name "*.css" -type f -printf '%s\n')
echo $total
In 2 steps:
1) ll *css | tr -s " " > filename.txt
2) awk 'BEGIN {x=0} {x+=$5} END {print x}' filename.txt

Size of files in subdirectories

I would like to know if there is an easy way to compute the total size of files in subdirectories in unix? I am interested in all the .js files in a folder with subdirectories and I am trying to use du -ah and grep *.js but does not work. Any help is appreciated. thanks
find . -iname "*.js" -ls | awk '{sum += $7} END {print sum}'
I dont think there is a way with du, but you can use awk
This is for all java files:
> find . -name "*.java" | xargs du -a | awk '{sum+=$1}END{print sum}'
2774
so you can modify this to :
find . -name "*.js" | xargs du -a | awk '{sum+=$1}END{print sum}'
Try below command..... It will print the total at the end...
find . -name '*.js' -exec du {} \; | awk 'sum=sum+$1; END{print sum " total" }'
find . -name '*.js' -exec stat -c %s '{}' + | awk '{ sum += $0 } END { print sum }'

searching for part of a filename (UNIX)

On unix I have files which have been renamed as their original name follwed by _inode number (ie the file dog would be renamed dog_inodeno). I am now trying to remove the inode no so i can search for the original file name elsewhere. Does anyone know how I can do this and teh coding neccesary.
Thanks
This should do the job:
find . -type f -name "*_[0-9]*" -exec \
sh -c 'for i do
b=$(basename "$i")
r=$(basename "$i" "_$(ls -i "$i"|awk "{print \$1}")")
if [ "$b" != "$r" ]; then
echo mv "$i" "$(dirname $i)/$r"
fi
done' sh {} +
Replace echo mv by mv for the script to actually rename the files.
The solution here will do rename your files only if the inode number of a file is part of the file's name in the mentioned format, which is what the OP wants.
Solution is successfuly tested at my end.
find ./ -name "*_[0-9][0-9][0-9][0-9][0-9][0-9]" -exec sh 'rename-files.sh' {} \;
Store the below script for the find command to be successful.
#Script Name: rename-files.sh
#!/bin/bash
#Store the result of find
find_result=$1
#Get the existing file name
fname_alone=`expr ${find_result} : '.*/\(.*\)' '|' ${find_result}`
fname_with_relative_path=`expr ${find_result} : '.\(.*\)' '|' ${find_result}`
fname_with_full_path=`echo "$(pwd)${fname_with_relative_path}"`
#Get the inode number of file name
file_inode_no=`find ./ -name ${fname_alone} -printf '%i'`
#Read the end of name
end_of_name=`echo $fname_alone | awk -F "_" '{print $NF}' `
#Check if end of name contains its file's inode number
if [ $end_of_name -eq $file_inode_no ]
then
#Remove the inode number at the end of file name
new_name=`expr $find_result : '.\(.*\)_.*' '|' $find_result`
#Append the path of the file
renamed_to=`echo "$(pwd)${new_name}"`
#Rename your dog_inodeno to dog
mv $fname_with_full_path $renamed_to
fi
Hope this helps.

KSH sort filenames

I'm searching through a number of directories for "searchstring", and then running a script on each $file:
for file in `find $dir -name ${searchstring}'*'`;
do
echo $file >> $debug
script.sh $file >> $output
done
My $debug file yields the following:
/root/0007_searchstring/out/filename_20120105_020000.log
/root/0006_searchstring/out/filename_20120105_010000.log
/root/0005_searchstring/out/filename_20120105_013000.log
(filename is _yyyymmdd_hhmmss.log)
...
Is there a way to get find to order by filename or by mktime? Should I pipe find to sort first? Make an array then sort it as per this question?
If you want to ignore the directory path and just use the file name, then you should be able to use:
for file in `find $dir -name ${searchstring}'*' | sort --field-separator=/ --key=4`;
'ls -t' if you need to regenerate the list based on timestamp.
'sort -n' if the list is fairly static?
To sort by modification time, you can use stat with find:
$ find . -exec stat {} -c '%Y %n' \; | sort -n | cut -d ' ' -f 2
You can pipe the output of find through sort to sort by filename:
find $dir -name "${searchstring}*" | sort | while read file
do
echo "$file" >> $debug
script.sh "$file" >> $output
done

Resources