Я предлагаю:
#!/bin/bash
if (($EUID != 0)); then
if [[ -t 1 ]]; then
sudo "$0" "$@"
else
exec 1>output_file
gksu "$0 $@"
fi
exit
fi
# some example stuff
ls -l /root
echo "app: $0"
for f; do
echo ">$f<"
done
Вы можете grep
для ␀ символов с помощью Perl regex режим:
$ echo -ne "\0\0" > nul.bin
$ echo -ne "\0x\0" > non-nul.bin
$ grep -P "[^\0]" *.bin
Binary file non-nul.bin matches
Таким образом, можно использовать это:
for path in *.foo
do
grep -P "[^\0]" "$path" || echo "$path"
done
Я соглашаюсь с тем, что D_Bye говорит о нахождении корня проблемы.
Так или иначе, чтобы проверить, содержит ли файл только \0
и/или \n
Вы могли использовать tr
:
<file tr -d '\0\n' | wc -c
Который возвращается 0 для пустого указателя/новой строки и пустых файлов.
tr -d '\0\n'
решает проблему новой строки, которая затем только оставляет проблему (?) пустых файлов, перечисляемых в выводе... Это действительно обрабатывает каждый байт каждого файла, хотя (который может или не может быть проблемой), +1
– Peter.O
20.12.2012, 15:02
Я подозреваю, что те файлы редки, который является, у них нет дискового пространства выделенным им, они просто указывают размер файла (du
сообщил бы 0 для них).
В этом случае, с GNU находят, Вы могли сделать (предполагающий, что никакой путь к файлу не содержит символы новой строки):
find . -type f -size +0 -printf '%b:%p\n' | grep '^0:' | cut -d: -f2-
du
будет препятствовать царапать содержание каждого файла в файловой системе, таким образом, целая процедура не взяла бы 30 + минуты для завершения.
– Adam Ryczkowski
22.12.2012, 11:58
Вот маленькая программа Python, которая может сделать это:
import sys
def only_contains_nulls(fobj, chunk_size=1024):
first = True
while True:
data = fobj.read(chunk_size)
if not data:
if first:
return 1 # No data
else:
return 0
if data.strip("\0"):
return 1
first = False
if __name__ == '__main__':
with open(sys.argv[1]) as f:
sys.exit(only_contains_nulls(f))
И в действии:
$ printf '\0\0\0' > file
$ ./onlynulls file && echo "Only nulls" || echo "Non-null characters"
Only nulls
$ printf a >> file
$ ./onlynulls file && echo "Only nulls" || echo "Non-null characters"
Non-null characters
Можно проверить несколько файлов при помощи находки -exec
, xargs
, GNU parallel
, и подобные программы. С другой стороны, это распечатает имена файлов, с которыми нужно иметь дело:
files=( file1 file2 )
for file in "${files[@]}"; do
./onlynulls "$file" || printf '%s\n' "$file"
done
Примите во внимание, что, если Вы собираетесь передать вывод этого к другой программе, имена файлов могут содержать новые строки, таким образом, необходимо разграничить его по-другому (подходяще, с \0
).
Если бы у Вас есть много файлов, было бы лучше использовать опцию для параллельной обработки, так как это только читает один файл за один раз.
Найдите файлы, которые содержат только пустые символы '\0' и символы новой строки '\n'.
q
в sed заставляет каждый поиск файла выходить непосредственно после нахождения любого ненулевого символа в строке.
find -type f -name 'file-*' |
while IFS= read -r file ;do
out=$(sed -n '1=; /^\x00\+$/d; i non-null
; q' "$file")
[[ $out == "1" ]] && echo "$file"
done
Сделайте тестовые файлы
> file-empty
printf '%s\n' 'line1' 'line2' 'line3' > file-with-text
printf '%4s\n' '' '' xx | sed 's/ /\x00/g' > file-with-text-and-nulls
printf '%4s\n' '' '' '' | sed 's/ /\x00/g' > file-with-nulls-and-newlines
printf '%4s' '' '' '' | sed 's/ /\x00/g' > file-with-nulls-only
вывод
./file-with-nulls-and-newlines
./file-with-nulls-only
Определите псевдоним:
alias is_binary="python -c 'import sys; sys.exit(not b\"\x00\" in open(sys.argv[1], \"rb\").read())'"
Протестируйте:
$ is_binary /etc/hosts; echo $?
1
$ is_binary `which which`; echo $?
0
Рекурсивный поиск всех двоичных файлов:
IS_BINARY='import sys; sys.exit(not b"\x00" in open(sys.argv[1], "rb").read())'
find . -type f -exec bash -c "python -c '$IS_BINARY' {} && echo {}" \;
Чтобы найти все небинарные файлы, замените &&
на ||
.
Для использования GNU sed вы можете использовать опцию -z
, которая определяет строку как нулевую -завершенную строку, а также сопоставляет и удаляет пустые строки, например:
if [ "$( sed -z '/^$/d' "$file" | head -c 1 | wc -c )" -eq 0 ]; then
echo "$file contains only NULL!"
fi
Промежуточная команда head — это просто оптимизация.
Этот один -лайнер является наиболее эффективным способом поиска 100% nul-файлов с помощью GNU find
, xargs
и grep
(, предполагая, что последний построен с поддержкой PCRE):
find. -type f -size +0 -readable -print0 |
LC_ALL=C xargs -r0 grep -LP "[^\x00]" --
Преимущества этого метода перед другими предоставленными ответами::
Permission denied
предупреждений. grep
прекратит чтение данных из файлов после обнаружения любого не-нулевого байта (LC_ALL=C
, чтобы убедиться, что каждый байт интерпретируется как символ). grep
процессов эффективно проверяют несколько файлов. -
, обрабатываются правильно. Передача параметра -Z
в grep
и использование xargs -r0...
позволяет выполнять дальнейшие действия над файлами со 100 % NULL (, например :очистка):
find. -type f -size +0 -readable -print0 |
LC_ALL=C xargs -0 grep -ZLP "[^\x00]" -- |
xargs -r0 rm --
Я также рекомендую использовать опции find
-P
, чтобы избежать перехода по символическим ссылкам,и -xdev
чтобы избежать обхода файловых систем (например, :удаленное монтирование, деревья устройств, связывание монтирования и т.д. ).
Для игнорирования символа конца строки (s)должен работать следующий вариант (, хотя я не думаю, что это хорошая идея):
find. -type f -size +0 -readable -print0 |
LC_ALL=C xargs -r0 grep -LP "[^\x00\r\n]" --
Собираем все воедино, включая удаление ненужных файлов (100 % символов nul / newline ), чтобы предотвратить их резервное копирование:
find -P. -xdev -type f -size +0 -readable -print0 |
LC_ALL=C xargs -0 grep -ZLP "[^\x00\r\n]" -- |
xargs -0 rm --
Я не рекомендую включать пустые файлы (нулевые байты ), они часто существуют для оченьспецифическихцелей .
Вот сочетание и сокращение ответов @Tyson и @l0b0:
# --text: do not skip non-text files
grep --recursive --files-without-match -P '[^\0]'
Если вам нужен минимальный размер файла в один байт:
# -size +0c: more than zero bytes
find -type f -size +0 -exec grep --text --files-without-match -P '[^\0]' {} +
GNU grep 2.5.4
. Независимо от того, использую ли я--binary-files=text
или--binary-files=binary
, это дает atrue
результат для всех непустых значений данных, например."\0\0"
,"\0x\0"
,"abcd"
... Точный код, который я использовал:for typ in binary text ;do for dat in '\0\0' '\0x\0' 'abcd' '' ;do printf "$dat" >f; grep --binary-files=$typ -P '[^\0]' f >/dev/null && echo true || echo false; done; done
– Peter.O 21.12.2012, 05:37GNU grep) 2.10
. Эта более поздняя версия действительно дает ожидаемые результаты... так, запоздалый +1 – Peter.O 21.12.2012, 05:44printf '\0\n\0\0\n\n' > file
илиprintf '\n' > file
для этого вопросы. – Stéphane Chazelas 02.06.2015, 00:42\0
и\n
символы (даже нуль любого) были бы соответствием. – l0b0 02.06.2015, 01:59