Find the file with highest numeric value using shell script - bash

I have many files with alphanumeric names like
abc2,abc5,cat1,dog6,horse5,abc3,cat3,dog8,horse9,abc8
I want to find the file with highest numeric value and starts with abc. In this case the file I'm looking for is abc8 . I want a shell script to do this thing.
Could anyone please help me.
Thanks for your time.

You can use:
p=0; for f in abc*; do n="${f#abc}"; ((n>p)) && p=$n && of="$f"; done
echo "$of"
abc8

Another way
ls -d abc*|sort -nr |head -1

Related

Find a file in unix using shell

I am new to Unix and i have an assignment, where im struggling to find the solution
Find a given file in given directory and subdirectories recursively
If yes, print the full file path along with its size and word count, last modified time .
I tried using
find . -name "*.xlsx"
im getting some values
i want to do it in sh program
In shell i tried,
#!/bin/sh
file="/home/sample"
if[[$(find . -name "*.xlsx") -gt 0]]
then
echo"files are there"
fi
I need to get the values, instead im getting error. How to run the find in if statement.
Thanks
First issue was you need to have space between if and [[.. , Also space after echo and the string to print. Also add ; after ]]
Secondly, use -n inside if with find. It will test for a non-empty string. This will make your if statement and find work.
if [[ -n $(find . -name "*.txt") ]];
then
echo $PWD/*.txt # This will print full path of file.
wc *.txt | awk '{print "Word Count:",$1,"File Size:",$3,"Bytes" }' #Prints word count and size
fi
For getting word count and file size we can use wc command. First column gives the word count and third column gives the file size in bytes. You can use awk to print the columns.

Output into new column .CSV Shell

I am still new to Shell. In javascript it is super easy to parse all output into a new column. Allyou need is ,. But I am still struggling to do the same in Shell. I've traversed most of the anwsers on Stackoverflow, and still couldn't get it to work. Most of the anwsers are around cutting from an existing file and pasting into a new one etc. Pretty sure, somewhere I am making a simple syntax error.
At the moment I have this:
echo "Mq1:" >> ~/Desktop/howmanySKUs.csv
cd /Volumes/Hams\ Hall\ Workspace/Mannequin_1_WIP && ls |grep \_01.tif$ | wc -l | sed "s/,//" >> ~/Desktop/howmanySKUs.csv
It counts the amount of files in specified directory.
I get this:
But now I am trying to Output Mq1: in one column, and then the sum of found files in the 2nd column.
Desired Output:
Any help would be much appreciated.
You can directly append both the lines
cd /Volumes/Hams\ Hall\ Workspace/Mannequin_1_WIP && echo "Mq1:,"`ls |grep \_01.tif$ | wc -l` > ~/Desktop/howmanySKUs.csv

Incrementing variable in Bash -sed command

I have a bash script that I'm trying to put together that finds all of the images in a folder and then puts the names of those files into a pre-formatted CSV. I actually have the more complicated parts of it figured out and working well... I'm stuck on a really basic part. I have a variable that I need to increment for each file found, simple enough right? I've tried a bunch of different things and cannot for the life of me get it to increment. Here's the script I'm working with:
EDITED to show less context
i=0
find "$(pwd)" -maxdepth 1 -type f -exec file {} \; | awk -F: '{if ($2 ~/image/) print $1}' | grep -o -E '[^/]*$' | sed -e "s/^/$((++i))/" > "$(pwd)/inventory-$(date +%Y%m%d)-$(date +%I%M).csv"
I've tried incrementing it with i++, i=+1, i=i+1 as well as putting the dollar sign before the different iterations of the i variable... nothing seems to actually increment the variable. My best guess is that this isn't a true loop so it doesn't save the changes to the variable? Any guidance would be greatly appreciated!
The $((++i)) is performed by your shell. But the shell executes this line only once. This line cannot do what you need.
I would increment in inside awk, print it alongside the file name, and then combine output in the further commands.

Find missing files by their number?

I have a big list of ordered files with names like this
file_1.txt
file_2.txt
file_3.txt
file_6.txt
file_7.txt
file_8.txt
file_10.txt
In this case it is easy to see that files: file_4.txt,file_5.txt and file_9.txt are missing, but if i have a big list how can i find the missing files? i am just learning bash so i just know some simple examples. like this
for i in $(seq 1 1000) ;
do
if [i not in *.txt]; then
echo $i;
done
But this doesnt even work unless i erase the if [i not in *.txt];then line
so it just writes all the numbers between 1 and 1000.
I hope you can help me.
Thanks in advance.
If they are in a file then this should work
awk 'match($0,/([0-9]+)/,a){a[1]>max&&max=a[1];b[a[1]]++}
END{for(i=1;i<max;i++)if(!b[i])print "file_"i".txt"}' file
Output
file_4.txt
file_5.txt
file_9.txt
The suggestion from #user4453924 really helped me out. It does not have to be in a file, just pipe output from ls into his awk command, and you should be fine:
ls *.txt | awk 'match($0,/([0-9]+)/,a){a[1]>max&&max=a[1];b[a[1]]++}
END{for(i=1;i<max;i++)if(!b[i])print "file_"i".txt"}'
Outputs:
file_4.txt
file_5.txt
file_9.txt
Alternatively, if you prefer to do it in a two step fashion, it would be quite simple to pipe the output from ls into a file, and then use his command directly on the file, as it is:
ls *.txt > filelist.txt
awk 'match($0,/([0-9]+)/,a){a[1]>max&&max=a[1];b[a[1]]++}
END{for(i=1;i<max;i++)if(!b[i])print "file_"i".txt"}' filelist.txt
One way to do this is by
## TODO: You need to change the following path:
THELIST=/path/to/input-file
for i in $(seq 1 10);
do
FOUND=`grep "file_$i.txt" "$THELIST"` #look for file $i in $THELIST
#Note: double quotes were placed around $THELIST
# in case there is whitespace in the filename
[[ "$FOUND" == "" ]] && echo $i #if what you found is empty, then output $i
done
You can find info about [[ ... ]] here: What is the difference between single and double square brackets in Bash?
square-brackets

Bash Script - Copy latest version of a file in a directory recursively

Below, I am trying to find the latest version of a file that could be in multiple directories.
Example Directory:
~inventory/emails/2012/06/InventoryFeed-Activev2.csv 2012/06/05
~inventory/emails/2012/06/InventoryFeed-Activev1.csv 2012/06/03
~inventory/emails/2012/06/InventoryFeed-Activev.csv 2012/06/01
Heres the bash script:
#!/bin/bash
FILE = $(find ~/inventory/emails/ -name INVENTORYFEED-Active\*.csv | sort -n | tail -1)
#echo $FILE #For Testing
cp $FILE ~/inventory/Feed-active.csv;
The error I am getting is:
./inventory.sh: line 5: FILE: command not found
The script should copy the newest file as attempted above.
Two questions:
First, is this the best method to achive what I want?
Secondly, Whats wrong above?
It looks good, but you have spaces around the = sign. This won't work. Try:
#!/bin/bash
FILE=$(find ~/inventory/emails/ -name INVENTORYFEED-Active\*.csv | sort -n | tail -1)
#echo $FILE #For Testing
cp $FILE ~/inventory/Feed-active.csv;
... Whats wrong above?
Variable assignment. You are not supposed to put extra spaces around = sign. The following should work:
FILE=$(find ~/inventory/emails/ -name INVENTORYFEED-Active\*.csv | sort -n | tail -1)
... is this the best method to achive what I want?
Probably not. But the best way depends on many factors. Perhaps whoever writes those files, can put them in a right location in the first place. You can also check file modification time, but that could fail, too... So as long as it works for you, I'd say go for it :)

Resources