#linux #bash #unix #ksh #sequential-number
#linux #bash #unix #ksh #порядковый номер
Вопрос:
Я хочу добавить порядковый номер для каждого файла и его содержимого в каталоге. Порядковый номер должен иметь префикс имени файла, и для каждой строки его содержимого должен иметь тот же номер с префиксом. Таким образом, порядковые номера должны быть сгенерированы для всех файлов (для имен и их содержимого) во вложенных папках каталога.
Я попытался использовать функцию maxdepth, rename, print как часть. но он выдает ошибку, в которой говорится, что «-maxdepth» — недопустимый параметр.
У меня уже есть часть кода (для печати имен и содержимого текстовых файлов в каталоге), и к нему должна быть добавлена эта логика.
#!bin/bash
cd home/TESTING
for file in home/TESTING;
do
find home/TESTING/ -type f -name *.txt -exec basename {} ';' -exec cat {} ;
done
P.s — печать, переименование, максимальная глубина не работают
Если имя первого файла равно File1.txt и его содержимое упоминается как «Louis», тогда вывод для имени файла должен быть 1File1.txt и содержимое должно быть как «1Louis».То же самое следует заменить на 2 для второго файла. Таким образом, он должен пройти через все вложенные папки в каталоге и распечатать соответственно. У меня уже есть часть кода, и к нему следует добавить эту логику.
Ответ №1:
При выполнении cd в скрипте должна быть обеспечена отказоустойчивость. Вы можете выполнить команду в неправильном каталоге, если вы этого не сделаете.
При вашей попытке вывод будет таким же даже без цикла for, так как for file in home/TESTING
передается home/TESTING
только в качестве аргумента for
, поэтому он запускается только один раз. В случае for file in home/TESTING/*
это произошло бы иначе, как.
Я использовал find без --maxdepth
, поэтому он также будет просматривать все подкаталоги для *.txt
файлов. Если вы хотите, чтобы только текущий каталог $(find /home/TESTING/* -type f -name "*.txt")
можно было заменить на $(ls *.txt)
, пока у вас нет каталога, который заканчивается на .txt
, проблем не будет.
#!/bin/bash
# try cd to directory, do things upon success.
if cd /home/TESTING ;then
# set sequence number
let "x = 1"
# pass every file to for that find matching, sub directories will be also as there is no maxdeapth.
for file in $(find /home/TESTING/* -type f -name "*.txt") ; do
# print sequence number, and base file name, processed by variable substitution.
# basename can be used as well but this is bash built in.
echo "${x}${file##*/}"
# print file content, and put sequence number before each line with stream editor.
sed 's#^#'"${x}"'#g' ${file}
# increase sequence number with one.
let "x "
done
# unset sequence number
unset 'x'
else
# print error on stderr
echo 'cd to /home/TESTING directory is failed' >amp;2
fi
Замена переменной:
Есть еще кое-что, я выбрал только эти 4, поскольку они похожи.
${var#pattern}
— Используйте значение var после удаления текста, соответствующего шаблону слева
${var##pattern}
— То же, что и выше, но удалите самую длинную соответствующую часть вместо самой короткой
${var%pattern}
— Используйте значение var после удаления текста, соответствующего шаблону справа
${var%%pattern}
— То же, что и выше, но удалите самую длинную соответствующую часть вместо самой короткой
So ${file##*/}
примет переменную $file и удалит каждый символ *
до последней ##
косой черты /
. $file
Значение переменной не изменяется этим, поэтому оно по-прежнему содержит путь и имя файла.
sed 's#^#'"${x}"'#g' ${file}
sed — это редактор потоков, для этого конкретного есть целые книги о его использовании. Обычно он помещается в одинарные кавычки, поэтому 's#^#1#g'
добавит 1 в начало каждой строки в файле. s
это подстановка, ^
это начало файла, 1
это текст, g
является глобальным, если вы не поместите туда g, это затронет только первый мач. #
это разделитель, он может быть и другим, как /
, например. Я отключил одинарную кавычку, чтобы разрешить использование переменной, и снова открыл одинарную кавычку.
Если вы хотите заменить текст, .txt на .php, вы можете использовать sed 's#.txt#.php#g' file
, .
имеют особое значение, они могут заменить любой отдельный символ, поэтому его нужно экранировать
, чтобы использовать его как текст. остальное не только file.txt
будет сопоставлено, но и file1txt
также.
Это может быть передано по конвейеру, в этом случае вам не нужно указывать имя файла, иначе вы должны указать хотя бы одно имя файла, в нашем случае это была ${file}
переменная, содержащая имя файла. Как я уже упоминал, подстановка переменных не изменяет значение переменной, поэтому она по-прежнему содержит имя файла с путем.
Комментарии:
1. Большое спасибо за ваш ответ. Я изменил x на x = x 1, так как столкнулся с некоторой проблемой с этим. Не могли бы вы, пожалуйста, объяснить мне эти команды (echo «$ {x}${file ##*/}» , sed ‘s # ^#'»${x}»‘# g’ $ {file}) подробно, если это возможно. Я пытаюсь это понять. Заранее спасибо.
2. Я обновил ответ, дайте мне знать, что-то неясно.
3. Большое вам спасибо за вашу помощь. Отличное объяснение! 🙂
4. Я допустил ошибку в примере sed.
.
может заменить любой символ, и в этом случае его необходимо экранировать.5. да, спасибо. Я должен изменить код в соответствии с новым требованием. Я задам это как отдельный вопрос в stack overflow и представлю код, который я сделал для него. Я сталкиваюсь с некоторыми проблемами с этим. Если вы получаете уведомление об этом, пожалуйста, ответьте, если найдете время. Это просто запрос. То, как вы объясняете вещи, легко понять и кристально ясно. Большое вам спасибо за то, что помогли мне разобраться в этом