I can find empty files in current directory with;
find . -empty -type f
I'd like to know
- How to write text to empty files which I found.
- How to empty the files if they already contain text.
I can find empty files in current directory with;
find . -empty -type f
I'd like to know
As you asked for a solution to do it using xargs
:
find -empty | xargs -I files sh -c 'echo hello > $1' -- files
sh
using xargs
while passing a file name each time which will be placed instead of $1
, simply $1
is the first argument we pass to a script.--
I'm telling that sh
command is done here and at the end I'm passing the file name as an argument to the sh
.Test:
$ mkdir /tmp/lab && cd /tmp/lab
$ touch 1 2 3 && echo foo > 2
$ find -empty
./1
./3
$ find -empty | xargs -I files sh -c 'echo hello > $1' -- files
$ cat 1 2 3
hello
foo
hello
I believe this should work:
find . -empty -type f -exec bash -c "echo 'hello' > {}" \;
Update to find empty files and then write to them and also find non-empty files and empty them:
find . -type f \( -empty -o -size +0b \) -exec bash -c "if [[ ! -s '{}' ]]; then echo 'hello' > '{}'; else cp /dev/null '{}'; fi" \;
Note:
This is run from the target folder, if not then just add the path to the command like so:
find /path/to/folder ...
man bash
: -c If the -c option is present, then commands are read from the first non-option argument command_string. If there are arguments after the command_string, they are assigned to the positional parameters, starting with $0.
Aug 4, 2017 at 14:05
You could also use a shell loop...
First, to make globbing recursive to mirror the action of find
, turn on globstar
shopt -s globstar
Then find the files
for f in **; do [[ -f "$f" ]] && [[ ! -s "$f" ]] && echo "$f"; done
You will see all the empty files. The -s
condition of test
means the file is longer than 0 bytes. Using ! -s
you can find files of zero length. -f
checks the file is a regular file.
Now make a slight adjustment to the command to write to the files:
for f in **; do [[ -f "$f" ]] && [[ ! -s "$f" ]] && echo "hello" > "$f"; done
You also said you want to know how to empty the files if they are not empty. The simplest way to empty a file is to truncate it with redirection
> foo
empties foo
of any content (or creates empty file foo
if it does not exist). So, to empty files that contain text (please be aware that this will destroy data in files; make sure you are running this command in the correct directory) you can use:
for f in **; do [[ -f "$f" ]] && if [[ -s "$f" ]] && > "$f"; done
You can combine the two commands, to write to files that are empty, and empty files that contain text:
for f in **; do [[ -f "$f" ]] && if [[ ! -s "$f" ]]; then echo "hello" > "$f"; else > "$f"; fi; done
or more readably (please check the current directory first - this destroys data in files):
for f in **; do
[[ -f "$f" ]] && if
[[ ! -s "$f" ]]; then echo "hello" > "$f"
else > "$f"
fi
done
This means "for all the files in this directory and its subdirectories, test whether the file is a regular file, and if it is, then if it is empty, write "hello" in it, and if it is not empty, then empty it".
You can turn off globstar when done if you want (but it will be unset anyway when you start a new shell, for example by opening a new terminal, typing bash
or switching user):
shopt -u globstar
**
no longer expands to all files including subdirectories & their contents @solfish
find
and recurse into subdirectories
I don't quite understand the question, could you be more specific? If you want to write some text/code in a file, Vim works really well.
vim [File Path]
e.g.
vim /etc/hosts