情况:
我需要一个删除当前文件夹中所有文件的bash脚本,但名为“ .rmignore ”的文件中提到的所有文件除外。此文件可能包含相对于当前文件夹的地址,该地址也可能包含星号(*)。例如:
1.php
2/1.php
1/*.php
我尝试了什么:
GLOBIGNORE
,但效果不佳。我还尝试将find
与grep
一起使用,如下所示:
find . | grep -Fxv $(echo $(cat .rmignore) | tr ' ' "\n")
答案 0 :(得分:1)
这条线完美地完成了工作
find . -type f | grep -vFf .rmignore
答案 1 :(得分:1)
如果我们假设.rmignore
中的所有文件都没有在其名称中包含换行符,则以下内容可能就足够了:
# Gather our exclusions...
mapfile -t excl < .rmignore
# Reverse the array (put data in indexes)
declare -A arr=()
for file in "${excl[@]}"; do arr[$file]=1; done
# Walk through files, deleting anything that's not in the associative array.
shopt -s globstar
for file in **; do
[ -n "${arr[$file]}" ] && continue
echo rm -fv "$file"
done
注意:未经测试。 :-)此外,关联数组与Bash 4一起引入。
另一种方法可能是使用整个文件列表填充数组,然后删除排除项。如果您处理数十万个文件,这可能是不切实际的。
shopt -s globstar
declare -A filelist=()
# Build a list of all files...
for file in **; do filelist[$file]=1; done
# Remove files to be ignored.
while read -r file; do unset filelist[$file]; done < .rmignore
# Annd .. delete.
echo rm -v "${!filelist[@]}"
也未经测试。
警告:rm
后果自负。可能含有坚果。保持备份。
我注意到这些解决方案都不会处理.rmignore
文件中的通配符。为此,您可能需要一些额外的处理......
shopt -s globstar
declare -A filelist=()
# Build a list...
for file in **; do filelist[$file]=1; done
# Remove PATTERNS...
while read -r glob; do
for file in $glob; do
unset filelist[$file]
done
done < .rmignore
# And remove whatever's left.
echo rm -v "${!filelist[@]}"
而且......你猜对了。未经测试。这取决于$f
扩展为glob。
最后,如果您需要更重的解决方案,可以使用find
和grep
:
find . -type f -not -exec grep -q -f '{}' .rmignore \; -delete
这会为正在考虑的EACH文件运行grep
。而且它不是一个bash解决方案,它只依赖find
这是非常普遍的。
请注意,如果您的文件包含换行符,则所有这些解决方案都存在错误风险。
答案 2 :(得分:1)
将find
的出口传递给另一个命令被认为是不好的做法。您可以使用-exec
,-execdir
后跟命令,'{}'
作为文件的占位符,';'
表示命令结束。您还可以使用'+'
将命令组合在一起IIRC。
在您的情况下,您希望列出目录的所有争议,并逐个删除文件。
#!/usr/bin/env bash
set -o nounset
set -o errexit
shopt -s nullglob # allows glob to expand to nothing if no match
shopt -s globstar # process recursively current directory
my:rm_all() {
local ignore_file=".rmignore"
local ignore_array=()
while read -r glob; # Generate files list
do
ignore_array+=(${glob});
done < "${ignore_file}"
echo "${ignore_array[@]}"
for file in **; # iterate over all the content of the current directory
do
if [ -f "${file}" ]; # file exist and is file
then
local do_rmfile=true;
# Remove only if matches regex
for ignore in "${ignore_array[@]}"; # Iterate over files to keep
do
[[ "${file}" == "${ignore}" ]] && do_rmfile=false; #rm ${file};
done
${do_rmfile} && echo "Removing ${file}"
fi
done
}
my:rm_all;
答案 3 :(得分:0)
如果您有temp\formats.sas7bcat
,则可以使用合适的rsync忽略文件将空目录复制到目标目录。首先使用rsync
尝试一下,看看它会尝试什么,然后再运行它!
答案 4 :(得分:0)
答案 5 :(得分:0)
或者,您可能希望查看最简单的格式:
rm $(ls -1 | grep -v .rmignore)