[使用通配符时sed命令无法正常工作

问题描述 投票:0回答:2

我正在尝试使用'sed'命令删除与作为命令行参数给出的通配符模式匹配的文件的最后一行,并将文件从该目录移动到当前目录。代码如下:

DIR="/home/usr_name/trash/"
for file in "$@"
    do
        if [ $file != "-h" ] //ignore this line
        then
            temp="$DIR$file"
            sed '$d' "$DIR$file"
            mv $temp .
        fi
    done

代码正在移动文件,但是它不执行'sed'命令来删除最后一行。将通配符指定为,则会出现以下错误:

sed: can't read /home/usr_name/trash/ab*: No such file or directory
帮助我弄清楚这种情况。
linux bash shell sed wildcard
2个回答
1
投票
find "$DIR" -name "$file" \ -exec sed -i '$d' {} \; -exec mv {} "$DEST" \;

-name "$file"-这将告诉find搜索与通配符匹配的文件
    [-exec sed -i '$d' {} \;-对找到的每个文件执行sed {}代表文件]
  • [-exec mv {} "$DEST" \;-移动文件
  • 请注意,执行主管的顺序,移动后该文件将在旧位置不可用。
  • Edit:我最初假设'ab*'是整个脚本的带引号的参数。 answer让我想起了另一种可能性:您从没有任何以'ab'开头的文件的目录中运行脚本,在这种情况下'ab *'不会扩展,并且mv将在您的脚本中运行,但sed不(因为引用“ $ DIR $ file”,请参见bash的调试输出:

    sorin@testvm ~/tmp $ seq 1 2 > src/ab1 sorin@testvm ~/tmp $ seq 1 4 > src/ab5 sorin@testvm ~/tmp $ seq 1 3 > src/ab3 sorin@testvm ~/tmp $ bash -x test.sh ab* + DIR=src/ + for file in '"$@"' + '[' 'ab*' '!=' -h ']' + temp='src/ab*' + sed '$d' 'src/ab*' sed: can't read src/ab*: No such file or directory + mv src/ab1 src/ab3 src/ab5 . sorin@testvm ~/tmp $ 这正好涵盖了您的问题中描述的场景。


  • 0
    投票
    yourcript ab*

    shell尝试在当前目录中扩展通配符,然后将结果作为"$@"传递。如果当前目录中没有匹配项,则

    expanded通配符(在shell的传统默认配置中)现在是

    literal字符串ab*,将不再尝试进一步的通配符扩展。

    (Bash具有nullglob来更改此行为,因此不匹配任何文件的通配符将被替换为空;但这在这里实际上没有帮助。)如果通配符

    确实

    与某些文件匹配,则这些文件很可能不在另一个目录中,或者(在一般情况下)具有这些名称的文件将不是您实际要处理的文件。

    [在最坏的情况下,可能在当前目录中有[[are]]个与通配符匹配的文件[[and

    ],它们都在目标目录中重复了相同名称的文件。因此,如果您在当前目录和另一个目录中都具有ababc,但是另一个目录中也包含abecedaryabugida,则您的命令将只处理前两个,并且不会收到任何信息。警告其他两个从未匹配和处理。底线,可能需要重新考虑将完整路径传递给要处理到脚本中的文件的方法;然后,其余的工作就很容易了,脚本的行为将是可预测的,并且与其他文件处理实用程序的行为保持一致。

    您仍然需要使sed实际上修改每个文件。仅sed '$d' files不会更改files,只需将修改后的内容打印到标准输出即可。如果您有sed -i,则可以使用它。

    for file in "$@" do # Note added quotes if [ "$file" != "-h" ] # ignore this line then sed -i '$d' "$file" mv "$file" . fi done 用法:

    yourscript /home/usr_name/trash/ab*


    -2
    投票
    #!/usr/bin/env bash DIR="/home/usr_name/trash/" for file in *; do ##: loop through the files inside [[ ! -s $file ]] && continue ## skip empty files printf '%s\n' '$d' w | ed -s -- "${DIR}$file" ##: delete the last line with ed. mv -v -- "${DIR}$file" . ##: move the files in the current pwd. done

    --在这里(以防万一),如果您有一个以破折号开头的有问题的文件名,由于您首先拥有PATH,所以也不需要此文件。

    ((您的脚本中暗示您已经拥有)edmv不会将其解释为选项。

    未经测试,请先尝试使用一些测试文件,但这应该可以满足您的要求。

    © www.soinside.com 2019 - 2024. All rights reserved.