0

I search for some files and I want to replace old content with new content from other files, so I have

#!/bin/bash
find /home/old -path "*$1" -exec cat /home/new/$1 > {} \;

When I execut:

> sh find.sh 'blam.php'

Problem is the script is creating a file called {} in the same dir with find.sh

Dobi Caps
  • 57
  • 1
  • 8

2 Answers2

2

The problem you get is that > is part of shell syntax, and should be literal for find command and syntactic in exec command.

what you are trying to do may be done in two steps

  • generating script
  • executing the script

.

find /home/old -path "*$1" -printf 'cat /home/new/'"$1"' > %p\n' > script.sh
sh script.sh

this way allows to check the commands, or using pipe

find /home/old -path "*$1" -printf 'cat /home/new/'"$1"' > %p\n' | sh

another way less efficient because spwans a shell for each file

find /home/old -path "*$1" -exec sh -c 'cat "/home/new/$1" > {}' _ "$1" \; 
Nahuel Fouilleul
  • 18,726
  • 2
  • 31
  • 36
  • Good solutions, but can I pass argumnet $1 in -sh c like `-exec sh -c 'echo $1'`, is possible? – Dobi Caps Apr 24 '18 at 11:43
  • It's safer to pass it as an argument to the `sh` command, rather than embed it in the command: `find ... -exec sh -c 'echo $1' _ "$1"`. There are two different `$1`s here; the one in single quotes is the value of the original shell's (in double quotes). – chepner Apr 24 '18 at 11:44
  • 2
    So `-exec sh -c 'cat /home/new/$1 > {}' _ "$1" \;`. – chepner Apr 24 '18 at 11:45
  • updated from comment – Nahuel Fouilleul Apr 24 '18 at 11:55
  • Hey @chepner , is possible to pass a variable in -exec sh -c? Like `-exec sh -c 'echo $VAR' _ "$VAR"` – Dobi Caps Apr 25 '18 at 08:30
  • 1
    @DobiCaps, the variables are inherited from caller process, `env` can be used to set variable for a process, command passed by arguments : `-exec env VAR=123 sh -c 'echo "$VAR"' \;`, the syntax `_ "$1"` is used to set positional parameters from `sh -c` or `bash -c` command line arguments the `_` is for `$0` – Nahuel Fouilleul Apr 25 '18 at 11:55
  • from man bash `-c string If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0.` – Nahuel Fouilleul Apr 25 '18 at 11:59
1

The problem here is that > {} is not part of the find command. The script is first interpreted by the shell, and the meaning of > is handled by the shell before passing the stuff around it as arguments to execute:

$ set -- blam.php
$ set -x
$ find /home/old -path "*$1" -exec cat "/home/new/$1" > {} \;
+ find /home/old -path '*blam.php' -exec cat /home/new/blam.php ';'

If you want a copy of your file somewhere else, use cp.

chepner
  • 497,756
  • 71
  • 530
  • 681
l0b0
  • 55,365
  • 30
  • 138
  • 223