【问题标题】:xargs doesn't work on SUSExargs 在 SUSE 上不起作用
【发布时间】:2017-06-29 02:50:02
【问题描述】:

这个问题只出现在,它可以在ubuntu上运行,甚至可以通过在windows上运行

我的意思是用另一个词替换几个文件中的一个词。

这就是我正在尝试的:

$  grep -Inrs MY_PATTERN src/ | cut -d: -f1 | xargs sed -i 's/MY_PATTERN/NEW_WORD/g'

sed: can't read path/to/a/found/file_1: No such file or directory
sed: can't read path/to/a/found/file_2: No such file or directory
sed: can't read path/to/a/found/file_3: No such file or directory
...

知道

$  grep -Inrs MY_PATTERN src/ | cut -d: -f1
path/to/a/found/file_1
path/to/a/found/file_2
path/to/a/found/file_3

更新1

这也不行

$  grep -lZ -Irs MY_PATTERN src/ | xargs -0 ls

ls: cannot access path/to/a/found/file_1: No such file or directory
ls: cannot access path/to/a/found/file_2: No such file or directory
ls: cannot access path/to/a/found/file_3: No such file or directory
...

$ ls -al path/to/a/found/file_1 | cat -vet
-rw-r--r-- 1 webme 886 Feb  1 13:36 path/to/a/found/file_1$

更新2

$ whoami
 webme

$ uname -a
 Linux server_vm_id_34 3.0.101-68-default #1 SMP Tue Dec 1 16:21:37 UTC 2015 (ed01a9f) x86_64 x86_64 x86_64 GNU/Linux

UPDATE3

$ grep --version
grep (GNU grep) 2.7
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel and others, see <http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.


$ xargs --version
xargs (GNU findutils) 4.4.0
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Built using GNU gnulib version e5573b1bad88bfabcda181b9e0125fb0c52b7d3b

# My project path /home/users/webme/projects/my_project
$ df -T
 dl360d-01:/homeweb/users/webme nfs   492625920 461336576  31289344  94% /home/users/webme

$ id
 uid=1689(webme) gid=325(web) groups=325(web)

$ mount -v
/dev/vda2 on / type btrfs (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
debugfs on /sys/kernel/debug type debugfs (rw)
udev on /dev type tmpfs (rw,mode=0755)
tmpfs on /dev/shm type tmpfs (rw,mode=1777)
devpts on /dev/pts type devpts (rw,mode=0620,gid=5)
/dev/vda1 on /boot type ext3 (rw,acl,user_xattr)
/dev/vdb on /appwebinet type xfs (rw)
rpc_pipefs on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)
dl360d-01:/homeweb/users on /homeweb/users type nfs (rw,soft,bg,addr=xx.xx.xx.xx)
dl360d-01:/appwebinet/tools/list on /appwebinetdev/tools/list type nfs (ro,soft,sloppy,addr=xx.xxx.xx.xx)
dl360d-01:/homeweb/users/webme on /home/users/webme type nfs (rw,soft,bg,addr=xx.xxx.xx.xx)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
none on /var/lib/ntp/proc type proc (ro,nosuid,nodev)

我没有exportfs,我也没有sudo zypper install exportfs

【问题讨论】:

    标签: suse babun bash sed xargs suse


    【解决方案1】:

    bishop's helpful answer 在这种情况下是最简单和最强大的解决方案。
    这个答案对于 (a) 讨论 -d-n 选项,以及 (b) 如何预览 xargs 将执行的命令。

    据我了解,SUSE 使用 GNU 实用程序,因此您可以使用xargs -d'\n'

    grep -Inrs MY_PATTERN src/ | cut -d: -f1 | xargs -d'\n' sed -i 's/MY_PATTERN/NEW_WORD/g'
    

    xargs -d'\n' 确保每个输入行作为一个整体 被视为其自己的参数(使用空格保持文件名的完整性),同时仍然通过尽可能多的参数(通常,全部一次

    (相比之下,-n 1 会用空格分隔参数,并一次使用 1 个参数调用目标命令。)

    如果您想预览执行的命令,请使用辅助。 bash 命令:

    grep -Inrs MY_PATTERN src/ | cut -d: -f1 |
      xargs -d'\n' bash -c 'printf "%q " "$@"' _ sed -i 's/MY_PATTERN/NEW_WORD/g'
    

    继续阅读以获得解释。


    可选的背景信息。

    xargs 有自己的选项,-p,用于预览要执行的命令提示确认,但预览没有'不以在直接从 shell 调用命令时必须指示它们的方式反映参数边界

    一个简单的例子:

    $ echo 'hi, there' | xargs -p -d '\n' printf '%s'
    printf %s hi, there ?...
    

    xargs实际执行的是printf '%s' 'hi, there'等效,但这反映在-p 中提示。

    解决方法:

    $ echo 'hi, there' | xargs -d '\n' bash -c 'printf "%q " "$@"' _ printf '%s'
    printf %s hi\,\ there
    

    通用辅助 bash 命令 - bash -c 'printf "%q " "$@"' _,插入到目标命令之前 - 引用 xargs 传递的参数 - 按需,仅在必要时 - 以一种方式shell 需要将每个参数识别为单个参数,并用空格连接它们。

    最终结果是 一个 shell 命令 被打印出来,它是xargs 将执行的等效(不过,当你可以看到,不能保证输入的引用样式会保留)。

    【讨论】:

      【解决方案2】:

      我建议保持简单:

      $ grep -lZ -Irs foo * | xargs -0 sed -i 's/foo/bar/g'
      

      grep -l 仅输出匹配的文件名,这正是您在此管道中想要的。 grep -ZNUL 终止每个匹配的文件名,xargs -0 可以获取该名称。这允许带有嵌入空格的文件名在 grep 和 xargs 之间不受限制地传递。


      # show the structure
      $ tree
      .
      └── path
          └── to
              └── a
                  └── found
                      ├── file_1
                      ├── file_2
                      └── file_3
      
      # show the contents
      $ grep . path/to/a/found/file_*
      path/to/a/found/file_1:a foo bar
      path/to/a/found/file_2:a foo bar
      path/to/a/found/file_3:a foo bar
      
      # try it out
      $ grep -lZ -Irs foo * | xargs -0 ls -l
      -rw-rw-r-- 1 bishop bishop 10 Feb 13 09:13 path/to/a/found/file_1
      -rw-rw-r-- 1 bishop bishop 10 Feb 13 09:13 path/to/a/found/file_2
      -rw-rw-r-- 1 bishop bishop 10 Feb 13 09:13 path/to/a/found/file_3
      

      【讨论】:

      • 更新了我的帖子
      • -rw-r--r-- 1 webme 886 Feb 1 13:36 path/to/a/found/file_1$
      • @smarber 我无法重现。请参阅我的编辑。请提供uname -awhoami,以及完整的复制脚本,包括创建文件或实际的、未编辑的输出。
      • 我已经用新的尝试过的东西更新了我的帖子。很难不认为它主要来自suse
      • @smarber 我刚刚下载了OpenSUSE,把它放在一个虚拟机里,尝试了上面的步骤,它们对我有用。 VM 上的内核版本是 4.4.27-2。您的版本是 3.0.101,即ancientgrep --versionxargs --version 显示什么?这些文件驻留在哪种文件系统上?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-30
      • 2017-11-05
      • 1970-01-01
      • 2018-11-06
      • 1970-01-01
      • 1970-01-01
      • 2021-12-31
      相关资源
      最近更新 更多