Вопрос или проблема
Я хочу исключить все файлы C
, которые имеют соответствующий файл asm
. Файлы сборки заканчиваются на _x86_64.S
. Файлы C
имеют одинаковые имена, но с .c
вместо _x86_64.S
в конце. Как мне сделать что-то вроде:
find . -not -name *{_x86_64.S but replace with .c}
Так, например, если существуют my_func.c
и my_func_x86_64.S
, то файл my_func.c
будет исключен вышеуказанной командой.
Правка:
Ответ, предоставленный ниже, работает. Я забыл упомянуть, что использовал это в Makefile.
Вот что я делал:
ASM_FILES = $(shell find ./src/assembly/x86_64/ -name "*.S" -printf "-not -name \"*%f*\" -and ")
ASM_INCLUDE += -wholename "./src/assembly/x86_64/*.S" -or
EXCLUDE += $(subst _x86_64.S,.c,$(ASM_FILES))
Это работает, но я надеялся на что-то более чистое.
Что ж, что-то вроде [ -e "${1%.c}.asm" ]
проверит, есть ли у файла .c
, названного первым аргументом командной строки, соответствующий .asm
.
Таким образом, помня, что -exec
в команде find является условием, это можно использовать, чтобы распечатать все .c
файлы без соответствующего .asm
.
find . -name "*.c" -exec sh -c '! [ -e "${1%.c}.asm" ]' find-sh {} \; -print
Затем нам придется включить все остальное (предполагая, что вы хотите только обычные файлы), например:
find . -type f \( ! -name "*.c" -o
-name "*.c" -exec sh -c '! [ -e "${1%.c}.asm" ]' find-sh {} \; \
\) -print
Например, учитывая четыре файла bar.c foo.asm foo.c hello.txt
, это выведет:
./hello.txt
./foo.asm
./bar.c
Хотя это может быть немного медленно, так как для каждого .c
файла создается новый экземпляр оболочки.
В качестве альтернативы, вы можете сделать это в цикле оболочки с использованием **
для рекурсивного сопоставления (нужна команда shopt -s globstar
в Bash):
$ shopt -s globstar
$ for f in ./**/* ; do
case $f in *.c)
if [ -e "${f%.c}.asm" ]; then continue; fi
esac;
printf -- "%s\n" "$f"
done
./bar.c
./foo.asm
./hello.txt
(Обратите внимание, что есть различия между оболочками в том, как **
работает с символьными ссылками внутри дерева.)
Ответ или решение
Чтобы выполнить задачу, заключающуюся в исключении всех файлов на языке C, соответствующих существующим файлам сборки с окончанием в формате _x86_64.S
, можно воспользоваться командой find
в комбинации с различными параметрами и условными операциями. Рассмотрим решение проблемы более подробно.
Шаг 1: Поиск файлов C
Для начала нужно найти все файлы с расширением .c
. Команда выглядит следующим образом:
find . -name "*.c"
Шаг 2: Исключение файлов C с соответствующими asm файлами
Теперь необходимо исключить из этого списка те файлы, для которых существует файл с соответствующим именем, заканчивающим на _x86_64.S
. Делается это с помощью команды find
и проверки на существование.
Возможно использовать следующий подход:
find . -name "*.c" -exec sh -c 'for cfile; do
asmfile="${cfile%.c}_x86_64.S";
[ ! -e "$asmfile" ] && echo "$cfile";
done' sh {} +
Здесь мы используем конструкцию -exec
для вызова оболочки sh
, в которую передаем все найденные файлы C. Для каждого файла осуществляется проверка существования соответствующего asm файла.
Шаг 3: Комбинирование с другими типами файлов
Если нужно вывести также и другие типы файлов (например, текстовые файлы или asm файлы), кроме .c
, можно использовать следующую конструкцию:
find . -type f \( ! -name "*.c" -o -name "*.c" -exec sh -c 'for cfile; do
asmfile="${cfile%.c}_x86_64.S";
[ ! -e "$asmfile" ] && echo "$cfile";
done' sh {} + \) -print
Это позволит выводить все файлы, кроме тех, которые являются .c
и имеют соответствующие файлы сборки.
Разделение слежения за производительностью
Важно отметить, что такой подход может оказаться несколько медленным, поскольку для каждого файла .c
создается новая оболочка, что увеличивает накладные расходы. В случае, если производительность имеет первостепенное значение, можно рассмотреть вариант с использованием циклов оболочки, что может быть выполнено с помощью globstar
в bash
. Например:
shopt -s globstar
for f in ./**/* ; do
case $f in *.c)
if [ -e "${f%.c}_x86_64.S" ]; then continue; fi
esac
printf -- "%s\n" "$f"
done
Таким образом, вызывая зависимость по проверке файлов, мы можем достичь желаемого результата быстрее и более эффективно.
Выводы
В результате, используя команду find
в сочетании с конструкцией -exec
, вы сможете эффективно исключить файлы C, имеющие соответствующие ASM файлы, повысив таким образом качество управления исходными кодами в вашем проекте. В процессе работы не забывайте учитывать потенциальные накладные расходы на производительность в зависимости от количества проверяемых файлов и общего объема данных.