
У меня возникла проблема в ОС Linux, работающей под управлением версии SMB, когда абсолютный путь к каталогу в общей папке равенбольше 1024 байт, а компонент имени файла больше 256 байтслужба SMB дает сбой и блокирует все остальные службы сетевого доступа, такие как SSH и FTP, из-за чего компьютер отключается.
Чтобы сохранить систему от сбоев, я временно переместил группу папок, где, как я думаю, проблемный путь может находиться за пределами общей папки. Мне нужно найти файл и путь к файлу, которые превышают это ограничение, и переименовать их или удалить, что позволит мне вернуть большую часть файлов в общую папку.
Я пробовалнаходитьигрэпкоманды без успеха. Есть ли цепочка команд или скрипт, которые я могу использовать для поиска проблемных файлов и каталогов?
Пожалуйста, порекомендуйте.
решение1
Это написано на Bash и использует специфичные для него возможности (но похожие возможности доступны и в других оболочках). Он разработан для запуска из родительского каталога, общего для всех файлов и каталогов, которые вас интересуют. Он учитывает длину пути от /
туда и добавляет ее к длине каждого оцененного пути. Если вы не хотите этого делать, просто используйте lenpwd=0
вместо lenpwd=${#PWD}
. Это будет работать, если есть файлы с пробелами в именах, но не те, в которых есть символы новой строки (которые должны быть изгнаны в любом случае). Он выводит длину и спецификацию файла всего, что он находит и что соответствует критериям.
lenpwd=${#PWD}; find | while read -r path; do file=${path##*/}; if (( ${#path} + lenpwd > 1024 || ${#file} > 256 )); then echo "$((${#path} + lenpwd)) ${#file} $path"; fi; done
решение2
Не знаю, правильно ли я вас понял, но первая попытка:
for f in $( find /srv/smb -type f )
do
fname=$( basename "$f" )
pname=$( dirname "$f" )
l_fname=$( echo "$fname" | wc -c )
l_pname=$( echo "$pname" | wc -c )
if [ $l_fname -gt 256 ] ; then
# do somthing with $f when filename > 256b
rm -- "$f"
continue
fi
if [ $l_pname -gt 1024 ] ; then
# do something if path > 1024
echo "$f much too long!"
fi
done
Это просто я-не-тестировал-но-должен-работать-в-bash-и-equlas-shell-скрипте. Можете свободно добавлять проверку ошибок и другие полезные штуки...
решение3
Вот однострочный код, который выводит длину dirname, затем длину basename, затем dirname и, наконец, basename (для потомков). Я просто использовал текущий рабочий каталог, но это можно изменить. Это также можно расширить, чтобы вытащить значения, большие, чем ваши данные.
find `pwd` -exec dirname '{}' \; -exec basename '{}' \;
| awk '( NR%2 != 0){printf("%s ",$0);next}1 '
| awk '{print length($1)" "length($2)" "$1$2}'
Обновлять:
Чтобы отсортировать по длине имени каталога, добавьте в конец следующее:
| sort -nr
Чтобы отсортировать по длине базового имени, добавьте в конец следующее:
| sort -nr -k2
Обновление 2:
По комментарию автора, это заменит пробелы на знаки «+», что позволит работать со счетчиками.
find `pwd` -exec dirname '{}' \; -exec basename '{}' \;
| tr '[:blank:]' '+'
| awk '( NR%2 != 0){printf("%s ",$0);next}1 '
| awk '{print length($1)" "length($2)" "$1$2}'