Adding data line by line in file in Unix - unix

I am extracting file names from one command it returns many file names and i am putting them into one file
code :
echo `find ${FILE_SYSTEM}/${dir_name}/${sub_dir_name} -type f -size +${BADFILES_SIZE} -exec ls -1lutr {} \; | sort -rn | awk '{print $9}'` >> Somefile.txt
The problem here is that i am not getting file names on each line.
Its giving two filenames on 1 line.
But i want to have each filename on 1 line.
Eg :
/informatica/ETD/PC9/scripts/kamil/temp/temp1.txt /informatica/ETD/PC9/scripts/kamil/temp/temp2.txt
I am getting filenames as shown above and i want as shown below.
/informatica/ETD/PC9/scripts/kamil/temp/temp1.txt
/informatica/ETD/PC9/scripts/kamil/temp/temp2.txt
Please give ur suggestions,

The problem is that you're using echo and backticks. Don't! The echo flattens all its arguments (a list of two files, it seems) into a single line of output.
Wrong:
echo `find ${FILE_SYSTEM}/${dir_name}/${sub_dir_name} -type f -size +${BADFILES_SIZE} -exec ls -1lutr {} \; | sort -rn | awk '{print $9}'` >> Somefile.txt
Right:
find ${FILE_SYSTEM}/${dir_name}/${sub_dir_name} -type f \
-size +${BADFILES_SIZE} -exec ls -1lutr {} + |
sort -rn |
awk '{print $9}' >> Somefile.txt

Related

Sort Matched Files by Last Modified and Timestamp

I need to look for files that match a certain pattern of characters, then find the most recent file and display it. The below code isn't quite getting me there but, I think I'm close.
Code:
find /home/weather/data/blend/ -type f -name "*.ctl" -printf '%Ts\t%p\n' | sort -nr | cut -f2
Here's a working solution:
find . -mmin -720 -type f -name "*.ctl" -exec ls -t {} \; | cut -c 3-

xargs Format output while cating files

I am combining xargs with find and have a bunch of files which I want to cat
find something
A
B
C
Now I am doing
find something | xargs cat
I want to put Echo the name of the file and some display message between the cat outputs. I tried -t option but it displays all the commands on top. Is xargs the way to go here? If so how should I proceed?
Try:
find . -name something -exec echo "File:" {} \; -exec cat {} \;
This is safe even for files whose names contain spaces, newlines, or other difficult characters.
Example
Let's have these test files:
$ cat A
1
2
$ cat B
3
4
$ cat C
5
6
The command output looks like:
$ find . -name '[ABC]' -exec echo "File:" {} \; -exec cat {} \;
File: ./B
3
4
File: ./C
5
6
File: ./A
1
2
How it works
find . -name something
This starts the find command with whatever options you like
-exec echo "File:" {} \;
For every file found, this prints File: followed by its name.
-exec cat {} \;
This prints the contents of the file.
Using GNU Parallel it looks like this:
find something | parallel 'echo {}:; cat {}'
If you want to echo filename and print a message, it might be simpler to use two commands... Use find to get the list of files you want to cat and then use a while loop to echo filename and print your message.
find . -type f -name '*.txt' > tmp.txt;
while read f;
do
echo "MY MESSAGE $f";
cat $f;
done < tmp.txt

Can't seem to search just first line of text

I'm using the following to only search the first line of a file for the report name. It's searching the whole file instead. I thought NR==1 would only search the first line. I think I just have a bad syntax.
find /SYM/SYM000/REPORT/ -type f -mmin -480 \
-name '[0-9][0-9][0-9][0-9][0-9][0-9]' \
-exec awk '/My Report Title/,NR==1 {print FILENAME; exit}' {} \;
Any help is appreciated.
I just want to return the filename. It looks for the past eight hours with a 6 digit number as the filename mask.
hek2gml's answer contains the crucial pointer - you must use && for logical AND rather than a range - but the command can be made more efficient in two respects:
Short-circuit processing of a given input file so that processing stops after the first line.
Passing (typically) all files to a single awk call, by terminating the -exec primary with + rather than \;
find /SYM/SYM000/REPORT/ -type f -mmin -480 \
-name '[0-9][0-9][0-9][0-9][0-9][0-9]' \
-exec awk '/My Report Title/ { print FILENAME } { nextfile }' {} +
This command only ever looks at the 1st line of each input file.
nextfile is not strictly POSIX-compliant, so if your awk doesn't have it (GNU Awk, Mawk, and BSD/OSX Awk do - not sure about AIX), use (less efficient, because it must read all lines of each file):
find /SYM/SYM000/REPORT/ -type f -mmin -480 \
-name '[0-9][0-9][0-9][0-9][0-9][0-9]' \
-exec awk 'FNR == 1 && /My Report Title/ { print FILENAME }' {} +
If, in the absence of nextfile, you'd rather call awk once for each file (-exec terminator \;), as in the original solution attempt (reads only the first line of each file, but calls awk once for each file):
find /SYM/SYM000/REPORT/ -type f -mmin -480 \
-name '[0-9][0-9][0-9][0-9][0-9][0-9]' \
-exec awk '/My Report Title/ { print FILENAME } { exit }' \;
Looks like you assume that /My Report Title/,NR==1 will be a kind of a list of conditions separated by a ,. That assumption is wrong.
Right in this case would be to use the logical AND operator && to concatenate the conditions:
find /SYM/SYM000/REPORT/ -type f -mmin -480 \
-name '[0-9][0-9][0-9][0-9][0-9][0-9]' \
-exec awk '/My Report Title/ && NR==1 {print FILENAME; exit}' {} \;

find and then grep and then iterate through list of files

I have following script to replace text.
grep -l -r "originaltext" . |
while read fname
do
sed 's/originaltext/replacementText/g' $fname > tmp.tmp
mv tmp.tmp $fname
done
Now in the first statement of this script , I want to do something like this.
find . -name '*.properties' -exec grep "originaltext" {} \;
How do I do that?
I work on AIX, So --include-file wouldn't work .
In general, I prefer to use find to FIND files rather than grep. It looks obvious : )
Using process substitution you can feed the while loop with the result of find:
while IFS= read -r fname
do
sed 's/originaltext/replacementText/g' $fname > tmp.tmp
mv tmp.tmp $fname
done < <(find . -name '*.properties' -exec grep -l "originaltext" {} \;)
Note I use grep -l (big L) so that grep just returns the name of the file matching the pattern.
You could go the other way round and give the list of '*.properties' files to grep. For example
grep -l "originaltext" `find -name '*.properties'`
Oh, and if you're on a recent linux distribution, there is an option in grep to achieve that without having to create that long list of files as argument
grep -l "originaltext" --include='*.properties' -r .

Pipe output to parameter

So I wanted to write a simple command that counts one less than the number of files in my current directory. I have this command that comes close but is off by one.
ls | wc -l
How can I pipe this to bc so I can subtract it by one?
Thanks!
To pipe to bc you could use something like this
echo " $(ls | wc -l) - 1 " | bc
EDIT: replace the part in the $( ) with steve's answer, or any other command you need.
That's really not what you want to do. Use find instead:
find . -maxdepth 1 -type f | wc -l
Also, you can exclude hidden files, with:
find . -maxdepth 1 -type f ! -name ".*" | wc -l
For completeness, you can handle files containing newlines and spaces like:
find . -maxdepth 1 -type f -print0 | tr -dc '\0' | wc -c

Resources