2

I can find empty files in current directory with;

find . -empty -type f 

I'd like to know

  1. How to write text to empty files which I found.
  2. How to empty the files if they already contain text.
2
  • Could you please give an example with some files and what should happen to them? Also please explain why you want to do all that, it doesn't seem useful to me and I find it hard to understand. What do you want to achieve?
    – Byte Commander
    Aug 4, 2017 at 13:49
  • @ByteCommander, sorry if im unclear, wanna achieve to write inside of each empty file which i found for instance "hello"
    – solfish
    Aug 4, 2017 at 13:51

4 Answers 4

4

As you asked for a solution to do it using xargs:

find -empty | xargs -I files sh -c 'echo hello > $1' -- files

Notes

  • We are running a 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.
  • Using -- 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
4
  • could you tell this part pls ? "sh -c 'echo hello > $@ ' -- files" thanks @Ravexina
    – solfish
    Aug 4, 2017 at 14:24
  • Updated the answer ...
    – Ravexina
    Aug 4, 2017 at 14:29
  • really thanks i m making you tired with questions
    – solfish
    Aug 4, 2017 at 14:33
  • @solfish you're welcome, it's fine ;) see my updates again ...
    – Ravexina
    Aug 4, 2017 at 14:39
3

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 ...
3
  • why use bash -c in there @George?
    – solfish
    Aug 4, 2017 at 14:02
  • can i use xargs ? how?
    – solfish
    Aug 4, 2017 at 14:03
  • See 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
2

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
7
  • what is shopt - u globstar your explanation, what changes if not use on script @Zanna?
    – solfish
    Aug 5, 2017 at 8:56
  • it turns off globstar, so globbing with ** no longer expands to all files including subdirectories & their contents @solfish
    – Zanna
    Aug 5, 2017 at 8:58
  • so , if on status i can reach every file , off status not, right?
    – solfish
    Aug 5, 2017 at 9:00
  • that's right @solfish - that's why I set it at the start of my answer, so that globbing will behave like find and recurse into subdirectories
    – Zanna
    Aug 5, 2017 at 9:01
  • hımm , and it is just useful with '**' to find files and directiories, i think @Zanna?
    – solfish
    Aug 5, 2017 at 9:03
1

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
1
  • no, i dont mean it, after finding all empty files i d like to write all inside same script/text
    – solfish
    Aug 4, 2017 at 13:55

Not the answer you're looking for? Browse other questions tagged .