bash:处理管道和IFR中的文件名

bash:处理管道和IFR中的文件名,bash,Bash,我的情况是,我有一个古老的目录,里面装满了文件,在这个目录中,一个同样古老(而且写得很糟糕)的应用程序创建了文件。多年来,已经创建了数百个带有前导、尾随或嵌入空格或其他“特殊”字符的文件。我想把这乱七八糟的东西收拾干净 我可以生成一个积极使用的文件列表。我可以将活动文件与现有文件的完整列表进行比较,并生成非活动文件的列表。我现在想删除非活动文件。我的问题是,在文件列表上循环似乎忽略了IFR设置 ACTIVE=`/bin/mktemp -t` NON_ACTIVE=`/bin/mktemp -t`

我的情况是,我有一个古老的目录,里面装满了文件,在这个目录中,一个同样古老(而且写得很糟糕)的应用程序创建了文件。多年来,已经创建了数百个带有前导、尾随或嵌入空格或其他“特殊”字符的文件。我想把这乱七八糟的东西收拾干净

我可以生成一个积极使用的文件列表。我可以将活动文件与现有文件的完整列表进行比较,并生成非活动文件的列表。我现在想删除非活动文件。我的问题是,在文件列表上循环似乎忽略了
IFR
设置

ACTIVE=`/bin/mktemp -t`
NON_ACTIVE=`/bin/mktemp -t`

...generate active file list... > $ACTIVE

/bin/ls -1 /path/to/all/files | \
    /bin/grep -Fxvf $ACTIVE > $NON_ACTIVE
我现在想删除
$NON\u ACTIVE
中列出的文件。我试过了

IFR=$(/bin/echo -en '\n\b')
使用前

/bin/rm `/bin/cat $NON_ACTIVE`
或者在列表上循环并删除每个文件。我还没有找到让我打击那些糟糕的文件的魔法。想法


我想我可以编辑
$NON_ACTIVE
并将
rm
前置到每一行,并将每个混乱的文件名用单引号括起来,但我想编写整个过程的脚本,并从中学习(或重新学习)一些东西,包括当单个命令行中包含的名称过多时:

#!/bin/bash
# ^-- needed because this uses bash-only features (particularly, bash 4.0 or newer)

# build an associative array with names of active files as keys
declare -A active_files-( )
while IFS= read -r -d '' filename; do
  active_files[$filename]=1
done < <(program_that_lists_active_files_with_NUL_delimiters)

# build a regular array of inactive files
inactive_files=( )
for file in *; do
  [[ ${active_files[$file]} ]] || inactive_files+=( "$file" )
done

# if you want to do only one rm call, and work with lists too long to fit on a single
# rm command line...
xargs -0 -- rm -f -- < <(printf '%s\0' "${inactive_files[@]}")

这是
IFS
,而不是
IFR
;请参阅…如果要比较两个列表,正确的工具是
comm
,而不是
grep
。请参阅常见问题解答36:另外,您不能安全地使用管道来分隔文件名,因为有效的UNIX文件名可以包含管道符号。使用NUL字符作为分隔符,并使用数组存储它们(因为NUL也不能存储在字符串变量中)。我切换到perl,我很高兴。谢谢
rm -f -- "${inactive_files[@]}"