LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   File name expansion with {} in gnu find and xargs (https://www.linuxquestions.org/questions/linux-software-2/file-name-expansion-with-%7B%7D-in-gnu-find-and-xargs-483764/)

anamericanjoe 09-15-2006 10:08 AM

File name expansion with {} in gnu find and xargs
 
I was thinking about suggesting a second possible solution to a problem posted at http://www.linuxquestions.org/questi...d.php?t=483730 when I discovered a problem of my own.

I believe that it is possible to use find to traverse a file system, select only certain types of files (such as *.txt files) and copy those files to one central location. I thought that gnu find would do the trick -- maybe piped to xargs if necessary (although I see no reason why I couldn't just use the exec flag...)

I ran into problems with I realized that I needed to place the name of the file find was currently proccessing in the middle of a command, as in:

Code:

find . -type f -name '*.txt' -exec cp current_file_name /tmp \;
My find man page says:

Quote:

All following arguments to find are taken to be arguments to the command until an argument consisting of `;' is encountered. The string `{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find. Both of these constructions might need to be escaped (with a `\') or quoted to protect them from expansion by the shell. The command is executed in the starting directory.
So I tried:

Code:

find . -type f -name '*.txt' -exec cp {} /tmp \;
and

Code:

find . -type f -name '*.txt' -exec cp '{}' /tmp \;
and

Code:

find . -type f -name '*.txt' -exec cp \{\} /tmp \;
However, find refused to expand {} to the current file name. Instead it took the {} literally and simply placed the current file at the end of the command, so find would actually process a command that looks something like this:

Code:

cp {} /tmp path/to/current_file_name
What is going wrong?

stress_junkie 09-15-2006 03:15 PM

I'm not having any trouble. In the following example I execute an ls command in the current directory. In that directory the backup, experiment, and testdisk-6.5-WIP listings are directories. The fix.file.permissions.sh listing is a regular file.

Code:

$ cd bin
$ mkdir /tmp/bin
$ ls
backup  experiment  fix.file.permissions.sh  testdisk-6.5-WIP
$ find . -exec cp {} /tmp/bin \;
cp: omitting directory `.'
cp: omitting directory `./experiment'
cp: omitting directory `./backup'
cp: omitting directory `./backup/old.good'
cp: omitting directory `./backup/keep'
cp: omitting directory `./testdisk-6.5-WIP'
cp: omitting directory `./testdisk-6.5-WIP/doc'
cp: omitting directory `./testdisk-6.5-WIP/linux'
cp: omitting directory `./testdisk-6.5-WIP/linux/l'
$ ls /tmp/bin
AUTHORS                      ie60fixes.css
COPYING                      iefixes.js
ChangeLog                    index.html
INFO                          intel_partition_table.html
NEWS                          linux
README                        linux_bootdisk.html
THANKS                        list-to-variable.sh
after_using_testdisk.html    lock_icon.gif
backup-command.txt            logo.png
backup-conf.txt              logo_sstic_transp.png
backup-exclude-files.txt      mail_icon.gif
backup-home.sh                main.css
backup-rootfs.sh              media_image.html
...

It put all of the regular files from the current working directory downward into the /tmp/bin directory. If you want to replicate a directory tree then you are better off using cp -R or the tar command or the pax command.

When I'm using the find command with the -name option I never use single or double quotes. I have found that the behavior of the find command seems to vary from one specific situation to the next when using -name '*' type parameters. Instead of using the quotes I use the \ escape character. So where you entered
Code:

find . -type f -name '*.txt' -exec cp {} /tmp \;
I would enter
Code:

find . -type f -name \*.txt -exec cp {} /tmp \;

anamericanjoe 09-16-2006 03:31 PM

OK, I think I know what I was doing wrong.

My find has an option similar to -exec: -ok. The man page says:

Quote:

-ok command ;
Like -exec but ask the user first (on the standard input); if the response does not start with `y' or `Y', do not run the command, and return false.

I was originally using -ok to test things out before I ran the actual command, so that's where I was getting confused.

The output of the -ok command really threw me off.

The -exec flag works exactly as it should.


All times are GMT -5. The time now is 01:48 AM.