How to find empty files and edit the header of them. by find and echo - linux

I have a folder contains ~30000 files and some of them are empty. I want to find them and put 'NON' as a header of the empty files.
my script is:
find -type f -empty -exec echo 'NON' {} \;
my output is:
NON ./file1
NON ./file2
NON ./file3
NON ./file4
but I want the 'NON' to write as a header of the file1 , file2 , file3 and file4.
Thanks in advance.

Why not just echo NON first and then do your find, with no need for exec?
Also I am not sure how you are running find without specifying a directory to search, so I have added the current directory to search below.
echo 'NON'
find . -type f -empty
The other possible interpretation of your question is that you want to add the string NON to all zero-length files. You can do that like this.
find . -type f -empty -exec sh -c "echo NON > {}" \;

Related

linux command line recursively check directories for at least 1 file with the same name as the directory

I have a directory containing a large number of directories. Each directory contains some files and in some cases another directory.
parent_directory
sub_dir_1
sub_dir_1.txt
sub_dir_1_1.txt
sub_dir_2
sub_dir_2.txt
sub_dir_2_1.txt
sub_dir_3
sub_dir_3.txt
sub_dir_3_1.txt
sub_dir_4
sub_dir_4.txt
sub_dir_4_1.txt
sub_dir_5
sub_dir_5.txt
sub_dir_5_1.txt
I need to check that each sub_dir contains at least one file with the exact same name. I don' need to check any further down if there are sub directories within the sub_dirs.
I was thinking of using for d in ./*/ ; do (command here); done but I dont know how to get access to the sub_dir name inside the for loop
for d in ./*/ ;
do
(if directory does not contain 1 file that is the same name as the directory then echo directory name );
done
What is the best way to do this or is there a simpler way?
from the parent directory
find -maxdepth 1 -type d -printf "%f\n" |
xargs -I {} find {} -maxdepth 1 -type f -name {}.txt
will give you the name/name.txt pair. Compare with the all dir names to find the missing ones.
UPDATE
this might be simpler, instead of scanning you can check whether file exists or not
for f in $(find -maxdepth 1 -type d -printf "%f\n");
do if [ ! -e "$f/$f.txt" ];
then echo "$f not found";
fi; done
Maybe not understand fully, but
find . -print | grep -P '/(.*?)/\1\.txt'
this will print any file which is inside of the same-named directory, e.g:
./a/b/b.txt
./a/c/d/d.txt
etc...
Similarly
find . -print | sed -n '/\(.*\)\/\1\.txt/p'
this
find . -print | grep -P '/(.*?)/\1\.'
will list all files regardless of the extension in same-named dirs.
You can craft other regexes following the backreference logic.

Insert empty line after the contents of a file in a new file

This is a simple problem, I'm just stuck on it. I am taking the contents of a bunch of different files and printing each file's name as a header before its contents. That much works. But I want to have an empty line separating the the contents of one file and the header for the next file's content.
I want it to look like:
File 1 header
File 1 contents
[empty space]
File 2 header
File 2 contents
I tried putting \n after "{}" in my code, but that didn't work. Any suggestions?
find . -type f -name '*_top_hits.txt' -print -exec cat {} \; > combinedresults.txt
You can just an empty echo as part of the find -exec as
find . -type f -name "*_top_hits.txt" -print -exec sh -c "cat {};echo" \; > combinedresults.txt
The echo just produces a single empty new-line after each file content. Also you don't need multiple -exec options rather use a single sub-shell.
You can try adding a second -exec:
find . -type f -name '*_top_hits.txt' -print -exec cat {} \; -exec echo \; > combinedresults.txt
One side effect of this is that a new line will be added at the end after the contents of the last file.

Bash - how to exclude directory with find command and how to get full path with find?

so I have the code right now down below, and I'm running into a few problems with it
I'm having trouble excluding the directories being outputted by
find ${1-.}
It is giving me the directories too instead of only names; I've tried different methods such as -prune etc.
I'm having trouble with deleting the empty files
The data given to me by
EMPTY_FILE=$(find ${1-.} -size 0)
Does not give me the correct path
Here is the output for that
TestFolder/TestFile
in this case I can't just do:
rm TestFolder/TestFile
As it is invalid path; since it needs ./TestFolder/TestFile
How would I add on the ./ or is there away to get the full path.
#!/bin/bash
echo "Here are all the files in the directory specified\n"
find ${1-.}
EMPTY_FILE=$(find ${1-.} -size 0)
echo "Here are the list of empty files\n"
echo "$EMPTY_FILE \n"
echo "Do you want to delete those empty files?(yes/no)"
read text
if [ "$text" == "yes" ]; then $(rm -- $EMPTY_FILE); fi
Any help is appreciated!
You want this:
#!/bin/bash
echo -e "Here are all the files in the directory specified\n"
# Use -printf "%f\n" to print the filename without leading directories
# Use -type f to restrict find to files
find "${1-.}" -type f -printf " %f\n"
echo -e "Here are the list of empty files\n"
# Again, use -printf "%f\n"
find "${1-.}" -type f -size 0 -printf " %f\n"
echo -e "Do you want to delete those empty files?(yes/no)"
read answer
# Delete files using the `-delete` option
[ "$answer" = "yes" ] && find "${1-.}" -type f -size 0 -delete
Also note that I've quotes "${1-.}" at all occurrences. Since it is user input, you can't rely on the input. Even if it is a path, it might still contain problematic characters, like spaces.
I'm having trouble excluding the directories being outputted by
find ${1-.}
It is giving me the directories too instead of only names
You are looking for the -type test. To instruct find to report only regular files, you could say
find ${1-.} -type f
That's probably what you really want, but what you actually asked (to exclude only directories) would be
find ${1-.} -not -type d
Excluding only directories will list symbolic links and special files, too.
in this case I can't just do:
rm TestFolder/TestFile
As it is invalid path; since it needs ./TestFolder/TestFile
Nonsense. ./TestFolder/TestFile means exactly the same thing as TestFolder/TestFile.
In any event, find does print paths starting at the specified starting path(s).
I have a feeling that I'm missing something from your question, but if all you need to do is exclude directories, just tell find to only look for files:
find . -type f -size 0 -delete
And then adjust that to suit your script. Hope this helps.
-size 0 -type f
rm with no option will not delete directories . Your claim that rm needs ./ is wrong anyway.

Search for text files in a directory and append a (static) line to each of them

I have a directory with many subdirectories and files with suffixes in those subdirectories (e.g FileA-suffixA FileB-SuffixB FileC-SuffixC FileD-SuffixA, etc).
How can I recursively search for files with a certain suffix, and append a user-defined line of text to those files? I feel like this is a job for grep and sed, but I'm not sure how I would go about doing it. I'm fairly new to scripting, so please bear with me.
You can do it like
find /where/to/search -type f -iname '*.SUFFIX' -exec echo "USER DEFINED STRING" >> \{\} \;
find searches in the suplied path
-type f finds only files
-iname '*.SUFFIX' find the .SUFFIXed names, case ignored
find ./ -name "*suffix" -exec bash -c 'echo "line_to_add" >> $1' -- {} \;
Basically you use find to get a list of the files. Then you use bash to echo append your line to that list.

find folders in a directory, without listing the parent directory

Having trouble listing the contents of a folder I'm not in, while excluding the actual folder name itself.
ex:
root#vps [~]# find ~/test -type d
/root/test
/root/test/test1
However I want it to only display /test1, as the example.
Thoughts?
There's nothing wrong with a simple
find ~/test -mindepth 1
Similarly, this will have the same effect:
find ~/test/*
as it matches everything contained within ~/test/ but not ~/test itself.
As an aside, you'll almost certainly find that find will complain about the -mindepth n option being after any other switches, as ordering is normally important but the -(min|max)depth n switches affect overall behaviour.
You can do that with -exec and basename:
find ~/test -type d -exec basename {} \;
Explanation:
The find ~/test -type d part finds all directories recursively under ~/test, as you already know.
The -exec basename {} \; part runs the basename command on {}, which is where all the results from the last step are substituted into.
Then you need -type f instead of -type d.
Or, if you want to display list of folders, excluding the parent -mindepth 1 (find ~/test -type d -mindepth 1).
And now that you edited it, I think what you want may be
find ~/test -type d -mindepth 1 |cut -d/ -f3-
But I think you need to be more specific ;-)
I just fixed it with sed
find $BASE -type d \( ! -iname "." \)|sed s/$BASE//g
Where $BASE is initial foldername.

Resources