Home > other >  What is good way to move a directory and then run a command to the file inside it using a bash shell
What is good way to move a directory and then run a command to the file inside it using a bash shell

Time:11-05

I would like to find txt files with find command and move the directory of the found file, and then apply a command to the file using a bash shell one-liner

For example, this command works, but the acmd is executed in the current directory.

$ find . -name "*.txt" | xargs acmd

I would like to run acmd in the txt file's direcotry.

Does anyone have good idea?

CodePudding user response:

From the find man page:--

 -execdir command ;

   -execdir command {}  
          Like  -exec, but the specified command is run from the subdirec‐
          tory containing the matched file,  which  is  not  normally  the
          directory  in  which  you started find.  This a much more secure
          method for invoking commands, as it avoids race conditions  dur‐
          ing  resolution  of the paths to the matched files.  As with the
          -exec action, the ` ' form of -execdir will build a command line
          to  process more than one matched file, but any given invocation
          of command will only list files that exist in the same subdirec‐
          tory.   If  you use this option, you must ensure that your $PATH
          environment variable  does  not  reference  `.';  otherwise,  an
          attacker  can run any commands they like by leaving an appropri‐
          ately-named file in a directory in which you will run  -execdir.
          The  same  applies to having entries in $PATH which are empty or
          which are not absolute directory names.  If find  encounters  an
          error, this can sometimes cause an immediate exit, so some pend‐
          ing commands may not be run at all. The  result  of  the  action
          depends  on  whether  the     or  the  ;  variant is being used;
          -execdir command {}   always returns true, while  -execdir  com‐
          mand {} ; returns true only if command returns 0.

CodePudding user response:

Just for completeness, the other option would be to do:

$ find . -name \*.txt | xargs -i sh -c 'echo "for file $(basename {}), the directory is $(dirname '{}')"'
for file schedutil.txt, the directory is ./Documentation/scheduler
for file devices.txt, the directory is ./Documentation/admin-guide
for file kernel-parameters.txt, the directory is ./Documentation/admin-guide
for file gdbmacros.txt, the directory is ./Documentation/admin-guide/kdump
...

i.e. have xargs "defer to a shell". In usecases where -execdir suffices, go for it.

  • Related