这是一篇问答帖子(不需要帮助,只是想帮助别人)。
最近处理了一些文件,在读取文件时遇到了困难
#version1 (error on files with spaces)
arrFiles[0]=0
folderLocation="/home/thenok/.local/share/recent"
for i in $(find "$folderLocation" ! -name "*~" -type f); do
arrFiles[0]=$[arrFiles[0]+1] arrFiles[arrFiles[0]]="$i"
echo arrFiles at pos ${arrFiles[0]} found ${arrFiles[arrFiles[0]]}
done
找到了一个(好的)解决方案:
#version2 works (ok but the global variable change bothered me)
IFS=$'\n' # make newlines the only separator
arrFiles[0]=0
folderLocation="/home/thenok/.local/share/recent"
for i in $(find "$folderLocation" ! -name "*~" -type f); do
arrFiles[0]=$[arrFiles[0]+1] arrFiles[arrFiles[0]]="$i"
echo arrFiles at pos ${arrFiles[0]} found ${arrFiles[arrFiles[0]]}
done
因为我不想改变 IFS 全局变量,所以我尝试在 find 中使用 exec 命令,但变量修改却是死路一条(没有版本 3 的代码,丢失了)
浏览了一下之后,我发现我们可以使用 read 来管道:
#version4 (horrible side effect of piping is that all variables altered between do and done do not last, maybe some people will like that)
arrFileNames[0]=0
folderLocation="/home/thenok/.local/share/recent"
find "$folderLocation" ! -name "*~" -type f | while read i; do
arrFileNames[++arrFileNames[0]]=${i} ;
echo arrFiles at pos ${arrFiles[0]} found ${arrFiles[arrFiles[0]]}
done
并成功让它发挥作用
#version5 works perfectly
folderLocation="/home/thenok/.local/share/recent"
arrFileNames[0]=0 && while read i; do arrFileNames[++arrFileNames[0]]=${i} ;
#insert custom code
echo arrFiles at pos ${arrFiles[0]} found ${arrFiles[arrFiles[0]]}
#end custom code
done < <( find "$folderLocation" ! -name "*~" -type f)
调试:
find "$folderLocation" ! -name "*~" -type f
#will show all files that match search location, '-type f' files not folders, '! -name "*~"' avoids backup files (usually created by office or text editors as a backup in case writing to disk failed)
#to search for a specific file name add '-name "*.pdf"' for all pdf files
#for folder path add '-path "*/torrent/*"'
#add ! to match opposite '! -path "*/torrent/*" ! -name "*.pdf"' folder name must not contain folder called torrent and must not be a pdf
#for only current folder add ' -maxdepth 1' as first argument ie 'find "$folderLocation" -maxdepth 1 ! -name "*~" -type f'
#for more complex conditions you can use '\(' '\)' '!' '-or' '-and'
find "$folderLocation" -maxdepth 1 \(\( ! -name "*~" -or -path "*/torrent/*" \) -and \( -name "*~" -and ! -path "*/torrent/*" \)\) -type f'
答案1
如果你能确定你的文件名都不包含换行符,那么使用 bash 你可以这样写:
mapfile -t arrFiles < <(find "$folderLocation" ! -name "*~" -type f)
仅限 bash 的方法:
shopt -s globstar nullglob extglob
arrFiles=( **/!(*~) )
但这将包括目录。要过滤掉它们,你可以
arrFiles=()
for f in **/!(*~); do
[[ -f $f ]] && arrFiles+=("$f")
done
检查数组:
declare -p arrFiles
答案2
希望人们发现它很有用,问答风格
版本 5 效果最好,但版本 2 效果也刚刚好。