Pipe output to parameter - unix

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

Related

UNIX: How to count number of rows in multiple files without headers

I have a set of files with similar naming pattern. I am trying to get the total row count of all the files combined sans the header in a go. But I am having trouble with the commands.
I have tried:
sed '1d' IN-Pass-30* | wc -l
and
awk 'END {print NR-1}' IN-Pass-30*
But each time it only subtracts the header count from just one file. What am I doing wrong here?
You were close. Wrap the sed command in a bash glob loop:
for f in IN-Pass-30*; do sed '1d' "$f"; done | wc -l
I propose following "simple" solution:
Prompt> find ./ -maxdepth 1 -name "IN-Pass-30*" | wc -l
53
Prompt> cat IN-Pass-30* | wc -l
1418549
Prompt> echo $(($(cat IN-Pass-30* | wc -l) - $(find ./ -maxdepth 1 -name "IN-Pass-30*" | wc -l)))
1418496
What does this mean?
Prompt> find ./ -maxdepth 1 -name "IN-Pass-30*" | wc -l
// find all files inside that directory without checking subdirectories.
// once they are found, count them.
Prompt> cat IN-Pass-30* | wc -l
// use `cat` to concatenate all files' content.
// at the end, count the amount of lines.
Prompt> echo $$(a - b))
// calculate the difference between a and b.
Prompt> echo $(command)
// show (or do whatever with it) the result of a command
Oh, the whole idea is that a header takes 1 line per file, so by counting the amount of lines in all the files, subtracted by the amount of files (which is the same as the amount of header lines), you should get the desired result.

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-

Remove underscores from all filenames within a directory

I have a folder "model" with files named like:
a_EmployeeData
a_TableData
b_TestData
b_TestModel
I basically need to drop the underscore and make them:
aEmployeeData
aTableData
bTestData
bTestModel
Is there away in the Unix Command Line to do so?
This will correctly process files containing odd characters like spaces or even newlines and should work on any Unix / Linux distribution being only based on POSIX syntax.
find model -type f -name "*_*" -exec sh -c 'd=$(dirname "$1"); mv "$1" "$d/$(basename "$1" | tr -d _)"' sh {} \;
Here is what it does:
For each file (not directory) containing an underscore in its name under the model directory and its subdirectories, rename the file in place with all the underscores stripped out.
You can do this simply with bash.
for file in /path/to/model/*; do
mv "$file" "${file/_/}"
done
If you have rename command available then simply do
rename 's/_//' /path/to/model/*
for f in model/* ; do mv "$f" `echo "$f" | sed 's/_//g'` ; done
Edit: modified a few things thanks to suggestions by others, but I'm afraid my code is still bad for strange filenames.
maybe this:
find model -name "*_*" -type f -maxdepth 1 -print | sed -e 'p;s/_//g' | xargs -n2 echo mv
Decomposition:
find all plain files in the directory model what contains at least one underscore, and don't search subdirectories
with the sed make filename adjustments - replace the _ with nothing
also print the old name
fed the two filenames to xargs what will rename the files with mv
The above is for a dry-run. When satisfied, remove the echo before mv for actual rename.
Warning: Will not work if filename contains spaces. If you have GNU sed you can
find . -name "*_*" -maxdepth 1 -print0 | sed -z 'p;s/_//g' | xargs -0 -n2 echo mv
and will works with a filenames with spaces too...
In zsh:
autoload zmv # in ~/.zshrc
cd model && zmv '(**/)(*)' '$1${2//_}'
marc#panic:~$ echo 'a_EmployeeData' | tr -d '_'
aEmployeeData
I had the same problem on my machine, but the filenames had more than one underscore. I used rename with the g option so that all underscores get removed:
find model/ -maxdepth 1 -type f | rename 's/_//g'
Or if there are no subdirectories, just
rename 's/_//g'
If you don't have rename, see Jaypal Singh's answer.
Use the global flag /g with your replace pattern to replace all occurrences within the filename.
find . -type f -print0 | xargs -0 rename 's/_//g'
Or if you want underscores replaced with spaces then use this:
find . -type f -print0 | xargs -0 rename 's/_/ /g'
If you like to live dangerously add the force flag -f in front of your replace pattern rename -f 's/_//g'

Adding data line by line in file in 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

UNIX find for finding file names not paired by

Is there a simple way to recursively find all files in a directory hierarchy, that do not have a matching file with a different extension?
For example the directory has a bunch of files ending in .dat
I want to find the .dat files that do not have an accompanying .out file.
I have a while loop that checks each entry, but that is slow for long lists...
I am using GNU find.
Perhaps something like this?
find . -name "*.dat" -print | sort > column1.txt
find . -name "*.out" -print | sort > column2.txt
diff column1.txt column2.txt
I haven't tested it, but I think it's probably close to what you're asking for.
find . -name '*.dat' -printf "[ -f %p ] || echo %p\n" | sed 's/\.dat/.out/' | sh
I had to add a bunch of bells and whistles to the 1st solution, but that was a good start, thanks...
find . -print | grep -Fi '.dat' | grep -vFi '.dat.' | sort | sed -e 's/.dat//g' > column1.txt
find . -print | grep -Fi '.out' | grep -vFi '.out.' | sort | sed -e 's/.out//g' > column2.txt
sdiff -s column1.txt column2.txt | grep -F '<' | cut -f1 -d"<" > c12diff.txt

Resources