Я придумал это, но, к сожалению, это не влияет ни на какие файлы/папки в подпапках.
find . -exec rename "s/^\s+//" {} \;
Структура папок:
foo
|-- \ bar
`-- \ foo1
|-- \ bar1
`-- \ foo2
`-- \ bar2
решение1
Переименование необходимо производить снизу вверх.
Проблема в том, что вам нужно переименовать каталоги.снизу вверх. В противном случае команда попытается переименовать файлы и каталоги, находящиеся внутри уже перемещенных (переименованных) папок, и, таким образом, больше не сможет их найти.
Здесь можно использовать python
's в сочетании сos.walk()
topdown=False
В небольшом сценарии:
#!/usr/bin/env python3
import os
import shutil
import sys
for root, dirs, files in os.walk(sys.argv[1], topdown=False):
for f in files:
if f.startswith(" "):
shutil.move(root+"/"+f, root+"/"+f.strip())
for dr in dirs:
if dr.startswith(" "):
shutil.move(root+"/"+dr, root+"/"+dr.strip())
Использовать
- Скопируйте скрипт в пустой файл, сохраните его как
no_space.py
Запустите его командой:
python3 /path/to/no_space.py /path/to/directory/to/rename
решение2
Как отмечено в других ответах, главная проблема заключается в том, что ^
закрепляет началопуть, а не начало имени файла. Есть несколько способов обойти это с помощью find
и rename
: вероятно, самым безопасным будет использовать -execdir
вместо -exec
, чтобы все компоненты пути сократились до ./
, а затем заменить шаблон\./\s+
Также, если вы переименовываете каталогивозможно, включая предков других файлов/каталогов, которые должны быть переименованы, то вам следует выполнить обход в глубину.
Собирая все вместе,
find . -depth -name ' *' -execdir rename -vn -- 's#\./\s+##' {} +
или (функционально эквивалентно, но немного проще увидеть, что происходит) использование «заднего просмотра» нулевой длины для разделителя пути
$ find . -depth -name ' *' -execdir rename -vn -- 's#(?<=\./)\s+##' {} +
./ bar2 renamed as ./bar2
./ foo2 renamed as ./foo2
./ bar1 renamed as ./bar1
./ foo1 renamed as ./foo1
./ bar renamed as ./bar
[ПРИМЕЧАНИЕ: удалите, -n
как только убедитесь, что он делает то, что вам нужно]
решение3
Я думаю, проблема в выходном формате find, который включает полный путь. Так что для bar2 у вас будет
./ foo1/ foo2 /bar2
это переименование не будет понято правильно.
Решением является использование скрипта для рекурсивной обработки каждой папки следующим образом:
#!/bin/bash
# if argument given consider it is the directory to parse
if [ -n "$1" ]; then
cd "$1"
fi
# rename all files in current folder
find . -maxdepth 1 -printf '%f\0' | xargs -0r -n 1 rename -nono 's/^\s+//'
# No, repeat for all subfolders with current script (we are in the subfolder)
find . -maxdepth 1 -type d -not -name '.' -print0 | xargs -0r -n 1 "$(readlink -f $0)"