我对bash命令很陌生。谁能帮我解决这个问题?
我需要找到当前目录下的所有.txt文件,并在这些文件的开头添加一段文字。我写了下面的命令
find . -name *.txt | xargs sed -i '1iadd text here'
这个命令对所有非空文件都能正常工作。但是对于那些空的文件就不行了。我想这是因为 sed 命令在空文件中找不到第 1 行,因此命令无法执行。有没有其他的方法也能在空文件中添加文本?
该 ed
Unix文本编辑器可以做到这一点。
for f in *.txt; do
printf '%s\n' '0a' 'insert some text here' . w | ed -s "$f"
done
find . -type f -name '*.txt' -exec sh -c 'for f; do printf "%s\n" 0a "insert some text here" . w | ed -s "$f"; done' {} +
find . -type f -name '*.txt' -print0 | while IFS= read -rd '' file; do ed -s "$file" <<< $'0a\ninsert some text here\n.\nw\nq'; done
可以使用 ed
脚本。
cat script.ed
熄灭
0a
insert some text here
.
w
q
现在是 for loop
for f in *.txt; do ed -s "$f" < ./script.ed; done
用找。
find . -type f -name '*.txt' -exec sh -c 'ed -s "$1" < ./script.ed' sh {} \;
两者的结合。
find . -type f -name '*.txt' -exec sh -c 'for f; do ed -s "$f" < ./script.ed; done' _ {} +
第一行是 1
和行动是 i
(意思是插入),在您的例子中也是如此。ed
,这意味着它将无法与ed一起工作,因为文件是空的,不包含任何行,但在这里我使用的地址是 0
和行动是 a
也就是说 append
,作品。
该 script.ed
是一个任意的名字,而 ./
在 ./script.ed
指当前工作目录,如果您的 ed
脚本的绝对路径。ed
脚本。
一句话的提醒。ed
在原地编辑文件,所以一定要备份你正在编辑的文件,以防万一......
要改进简短的oneliners是很难的。有时候,准备一段典型的、自我解释的代码是很好的,不那么紧凑,有一些假设(这里:临时文件),但在100%的情况下都能工作,例如
for file in `ls *.txt`; do awk 'BEGIN {print "add text here"}{print$0}' $file > tmp.tmp | mv tmp.tmp $file; done
或者说(编辑过的):
for file in ./*.txt; do awk 'BEGIN {print "add text here"}{print$0}' "$file" > tmp.tmp | mv tmp.tmp "$file"; done
然后尝试混合解决方案。
EDIT:
如果你必须使用 find
, xargs
和 sed
和 sed
对于空文件不能正常工作,您可以在文件中追加空行,插入文本,然后删除追加的行。
find . -type f -name '*.txt' | xargs -I "%" sh -c 'echo "" >> "%"; sed -i -e "1iadd text here" -e "$ d" "%"'
在原地用 ex
:
ex -s '+0s/^/add text here/' '+:wq' my_file
从stdin到stdout。
ex -s '+0s/^/add text here/' '+%print' '+:wq' /dev/stdin
请注意,这只适用于单个文件,而不像。sed
.
所以针对你的情况。
$ ls
empty not_empty
$ stat --format '%n: %s' *
empty: 0
not_empty: 6
$ cat empty
$ cat not_empty
a
b
c
$ find . -type f | xargs -I '{}' ex -s '+0s/^/add text here/' '+:wq' '{}'
$ cat empty
add text here
$ cat not_empty
add text herea
b
c
注意: -I
用于强制xargs执行 ex
每个文件一次,而不是试图汇总参数。
为了完整起见,举一个从stdin到stdout的过滤器的例子。
$ printf "%s\n" hello world | ex -s '+0s/^/add text here/' '+%print' '+:wq' /dev/stdin
add text herehello
world
$ cat /dev/null | ex -s '+0s/^/add text here/' '+%print' '+:wq' /dev/stdin
add text here