2. Реализуем небольшую вспомогательную функцию, которая принимает путь к файлу в виде строки, а также диапазон пар для замены. Каждая пара для замены содержит шаблон и его замену. Проходя в цикле по диапазону, воспользуемся regex_replace
, передавая ему входную строку и принимая преобразованную строку. После этого вернем полученную строку:
template
static string replace(string s, const T &replacements)
{
for (const auto &[pattern, repl] : replacements) {
s = regex_replace(s, pattern, repl);
}
return s;
}
3. В функции main
сначала проверим командную строку. Принимаем аргументы из нее argv
— всегда имя исполняемого файла. Это значит, что если пользователь предоставит хотя бы одну пару или больше, то argc
должен быть 3
:
int main(int argc, char *argv[])
{
if (argc < 3 || argc % 2 != 1) {
cout << "Usage: " << argv[0]
<< "
return 1;
}
4. Как только мы убедились, что получили во входных значениях необходимые пары, заполним ими вектор:
vector
for (int i {1}; i < argc; i += 2) {
patterns.emplace_back(argv[i], argv[i + 1]);
}
5. Теперь можно проитерировать по файловой системе. Для простоты определим в качестве каталога, по которому нужно проитерировать, текущий каталог приложения. Затем возьмем только имена файлов без остальной части пути и преобразуем их соответственно списку шаблонов и замен, собранному ранее. Возьмем копию opath
, назовем ее rpath
и заменим часть имени файла новой:
for (const auto &entry :
recursive_directory_iterator{current_path()}) {
path opath {entry.path()};
string rname {replace(opath.filename().string(),
patterns)};
path rpath {opath};
rpath.replace_filename(rname);
6. Для всех файлов, чьи имена совпали с нашими шаблонами, выведем на экран строку, сигнализирующую о том, что мы переименовали их. Если полученное в результате переименования имя файла уже существует, то продолжать работу невозможно. Просто будем пропускать такие файлы. Вместо этого мы могли бы прикреплять какое-то число к пути или что-то еще с целью разрешить пересечение имен.
if (opath != rpath) {
cout << opath.c_str() << " --> "
<< rpath.filename().c_str() << '\n';
if (exists(rpath)) {
cout << "Error: Can't rename."
" Destination file exists.\n";
} else {
rename(opath, rpath);
}
}
}
}
7. Компиляция и запуск программы для примера каталога дадут следующий результат. Я поместил несколько картинок в формате JPEG в каталог, но задал для них разные окончания: jpg
, jpeg
и JPEG
. Затем выполнил программу, передав ей шаблоны jpeg
и JPEG
и выбрав замену jpg
для них обоих. В результате получил каталог с одинаковыми расширениями файлов:
$ ls
birthday_party.jpeg holiday_in_dubai.jpg holiday_in_spain.jpg
trip_to_new_york.JPEG
$ ../renamer jpeg jpg JPEG jpg
/Users/tfc/pictures/birthday_party.jpeg --> birthday_party.jpg
/Users/tfc/pictures/trip_to_new_york.JPEG --> trip_to_new_york.jpg
$ ls
birthday_party.jpg holiday_in_dubai.jpg holiday_in_spain.jpg
trip_to_new_york.jpg
Создаем индикатор эксплуатации диска
Мы уже реализовали инструмент, который работает как ls
в Linux/MacOS или dir в Windows, но, подобно этим утилитам, не выводит размер файлов в
Чтобы получить эквивалент размера каталога, нужно зайти во все подкаталоги и суммировать размеры всех файлов, содержащихся в них.
В данном примере мы реализуем инструмент, который делает именно это. Инструмент можно запустить для любого каталога, он определит размер всех его записей.
Как это делается
В этом примере мы реализуем приложение, которое итерирует по каталогу и перечисляет размеры файлов для каждой записи. Это просто для обычных файлов, но если мы смотрим на запись каталога, которая сама по себе является каталогом, то нужно заглянуть в него и суммировать размеры всех файлов, хранящихся в нем.