我正在尝试使用'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
帮助我弄清楚这种情况。
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 $
这正好涵盖了您的问题中描述的场景。
yourcript ab*
shell尝试在当前目录中扩展通配符,然后将结果作为"$@"
传递。如果当前目录中没有匹配项,则
expanded通配符(在shell的传统默认配置中)现在是literal字符串
(Bash具有ab*
,将不再尝试进一步的通配符扩展。nullglob
来更改此行为,因此不匹配任何文件的通配符将被替换为空;但这在这里实际上没有帮助。)如果通配符确实
与某些文件匹配,则这些文件很可能不在另一个目录中,或者(在一般情况下)具有这些名称的文件将不是您实际要处理的文件。[在最坏的情况下,可能在当前目录中有[[are]]个与通配符匹配的文件[[and
],它们都在目标目录中重复了相同名称的文件。因此,如果您在当前目录和另一个目录中都具有ab
和abc
,但是另一个目录中也包含abecedary
和abugida
,则您的命令将只处理前两个,并且不会收到任何信息。警告其他两个从未匹配和处理。底线,可能需要重新考虑将完整路径传递给要处理到脚本中的文件的方法;然后,其余的工作就很容易了,脚本的行为将是可预测的,并且与其他文件处理实用程序的行为保持一致。您仍然需要使
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*
#!/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,所以也不需要此文件。
((您的脚本中暗示您已经拥有)ed
和mv
不会将其解释为选项。未经测试,请先尝试使用一些测试文件,但这应该可以满足您的要求。