英文:
Bash find files and loop contents
问题
从这个存储库@andrew8088/dotfiles/blob/main/install/bootstrap.sh中借用,我正在尝试使用那里的现有代码来循环我的MacOS $DOTFILES存储库以查找links.prop
文件,读取文件内容并运行适当的符号链接。
问题是当我运行bash install/boostrap.sh
并使用下面的片段时,我没有得到预期的结果。
install_dotfiles () {
info 'installing dotfiles'
local overwrite_all=false backup_all=false skip_all=false
find -H "$DOTFILES" -maxdepth 2 -name 'links.prop' -not -path '*.git*' | while read linkfile
do
echo $linkfile
cat "$linkfile" | while read line
do
echo $line;
local src dst dir
src=$(eval echo "$line" | cut -d '=' -f 1)
dst=$(eval echo "$line" | cut -d '=' -f 2)
dir=$(dirname $dst)
mkdir -p "$dir"
link_file "$src" "$dst"
done
done
}
输出
[ .. ] installing dotfiles
/Users/username/github/dotfiles/zsh/links.prop
/Users/username/github/dotfiles/git/links.prop
[ OK ] /Users/douglasbeaumont/.env.sh file already exists, skipping
[ OK ] All installed!
它可以找到文件,但无法读取内容。
zsh/links.prop
中有一行$DOTFILES/zsh/rc.zsh=$HOME/.zshrc
。
英文:
Taking from this repo @andrew8088/dotfiles/blob/main/install/bootstrap.sh I'm trying to use the existing code there to loop my MacOS $DOTFILES repo to find links.prop
files, read the contents of the file and run the appropriate symlink.
The problem is when I run the bash install/boostrap.sh
with the below snippet I don't get the expected results.
install_dotfiles () {
info 'installing dotfiles'
local overwrite_all=false backup_all=false skip_all=false
find -H "$DOTFILES" -maxdepth 2 -name 'links.prop' -not -path '*.git*' | while read linkfile
do
echo $linkfile
cat "$linkfile" | while read line
do
echo $line;
local src dst dir
src=$(eval echo "$line" | cut -d '=' -f 1)
dst=$(eval echo "$line" | cut -d '=' -f 2)
dir=$(dirname $dst)
mkdir -p "$dir"
link_file "$src" "$dst"
done
done
}
output
[ .. ] installing dotfiles
/Users/username/github/dotfiles/zsh/links.prop
/Users/username/github/dotfiles/git/links.prop
[ OK ] /Users/douglasbeaumont/.env.sh file already exists, skipping
[ OK ] All installed!
It finds the files fine but won't read the contents.
zsh/links.prop
has the line $DOTFILES/zsh/rc.zsh=$HOME/.zshrc
.
答案1
得分: 2
考虑这个示例脚本:
#!/bin/bash
printf ''%s' ''test data'' > testfile
while read -r line ; do
echo "'$line'"
done < testfile
它什么也不输出,但如果你 cat testfile
,显然已经写入了内容。这是怎么回事?
问题在于如果 read
在遇到换行符之前遇到文件结束,则会以非零状态退出,这导致 while
循环终止。如果你的文件只有一行,并且没有以换行符结尾,就像上面的 testfile
一样,它看起来好像内容没有被读取,但实际上不是这种情况。
如果不能保证每行都以换行符结尾,那么有一个解决方法:
#!/bin/bash
printf ''%s' ''test data'' > testfile
while read -r line || [[ -n "'$line'" ]] ; do
echo "'$line'"
done < testfile
未终止的行仍会导致 read
以非零状态退出,但因为 line
仍然有内容,你可以在退出循环之前检查是否有内容,并在处理后退出循环。
英文:
Consider this sample script:
#!/bin/bash
printf '%s' 'test data' > testfile
while read -r line ; do
echo "$line"
done < testfile
It prints nothing, but if you cat testfile
it's clearly populated. What gives?
The problem here is that read
exits with a non-zero status if it encounters end-of-file before a newline, which causes the while loop to terminate. If your file only has a single line and it's not newline-terminated, like testfile
above, then it will look like the contents aren't being read but that's not actually the case.
If you can't guarantee every line is newline-terminated, then there is a workaround:
#!/bin/bash
printf '%s' 'test data' > testfile
while read -r line || [[ -n "$line" ]] ; do
echo "$line"
done < testfile
The unterminated line will still cause read
to exit non-zero, but because line
is still populated you can follow that up with a check that there's something in it and process it before exiting the loop.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论