locate
буферизует поток STDOUT, вам необходимо сделать STDOUT для locate
небуферизованным (или буферизованным по строке).
Если вы работаете в системе GNU, вы можете использовать stdbuf
(поставляется с GNU coreutils
).
Чтобы сделать STDOUT locate
небуферизованным:
stdbuf -o0 locate something | ...
Буферизованная строка:
stdbuf -oL locate something | ...
Проверьте man stdbuf
, чтобы получить больше информации.
Я бы просто использовал для этого цикл bash:
for i in **/*.txt; do mkdir "${i%.txt}"; done
Если я запустил это в вашем примере, я получу:
$ tree
.
├── 1
│ └── 01-01-2015.txt
├── 2
│ └── 02-02-2016.txt
└── 3
└── 03-03-2017.txt
3 directories, 3 files
$ shopt -s globstar
$ for i in **/*.txt; do mkdir "${i%.txt}"; done
terdon@oregano foo $ tree
.
├── 1
│ ├── 01-01-2015
│ └── 01-01-2015.txt
├── 2
│ ├── 02-02-2016
│ └── 02-02-2016.txt
└── 3
├── 03-03-2017
└── 03-03-2017.txt
6 directories, 3 files
globstar
- это опция bash, описанная в man bash
:
globstar
Если установлено, шаблон
**
, используемый в контексте раскрытия имени пути, будет соответствуют всем файлам и нулю или более каталогов и подкаталогов. Если за шаблоном следует/
, совпадают только каталоги и подкаталоги.
Итак, после включения его с помощью shopt -s globstar
шаблон ** / *. Txt
найдет все файлы (или каталоги), имена которых заканчиваются на . txt
.
$ {i% .txt}
- это синтаксис оболочки для удаления подстроки. Общий формат - $ {variable% string}
, и он удалит первый экземпляр string
из конца переменной. Итак, $ {i% .txt} "
будет именем файла (включая родительские каталоги) за вычетом .txt
. Поэтому [передав его в mkdir
] создаст нужный каталог.
Лично я считаю, что приведенный выше синтаксис намного проще, но вот как это сделать с помощью find
:
find . -name '*.txt' -exec sh -c 'mkdir ${0%.txt}' {} \;
Здесь команда -exec {}
заменит {}
с каждым из результатов найти
, а затем выполнить для него команду
. Поскольку эта команда является вызовом sh -c
, sh
примет {}
в качестве нулевого позиционного параметра, $ 0
. Итак, мы запускаем ту же замену оболочки, как описано выше, чтобы создать каталог.
find example -name \*.txt | sed 's/\.txt$//' | xargs -n 1 mkdir
Предупреждение: для этого необходимо, чтобы ваши пути не содержали символы новой строки.
Изменить: см. Комментарий Тердона, если вы используете инструменты GNU.