На этот вопрос уже есть ответ здесь:
У меня есть каталог с огромным количеством файлов с разными расширениями. Что я хочу сделать, так это переместить каждое расширение в папку с именем само расширение, и эти файлы без расширения переместятся в папку с именем unkown
.
Например, у меня есть файлы a.txt
, b.txt
, a.pdf
, b.pdf
, a.mp4
, файл
, новый файл
....
Результатом будет 4 каталога с именами txt
, pdf
, mp4
, unkonw
txt
каталог содержит файлы a.txt
, b.txt
каталог pdf
содержит файлы a.pdf
, ] b.pdf
каталог mp4
содержит файлы a.mp4
каталог unkonw
содержит файлы файл
, ] новый файл
Вот иначе:
mkdir -p unknown;
for f in *; do
[[ $f =~ \. ]] && mkdir -p "${f##*.}" &&
mv "$f" "${f##*.}"/ ||
mv "$f" unknown/; done
&&
означает, "выполняет команду справа, только если команда слева была успешна". ||
означает, "выполняет команду справа, только если команда слева перестала работать". Эти два объединенные символа могут работать как if/else
блок. mkdir -p unknown;
: создайте unknown
каталог. -p
есть ли так, чтобы mkdir
не будет жаловаться, существует ли каталог. for f in *
: для всех файлов и каталогов в текущем каталоге.[[ $f =~ \. ]] &&
: если текущее имя файла/dir содержит a .
, если это имеет расширение, то...mkdir -p "${f##*.}"/
: конструкция ${var##pat}
удалит самое долгое соответствие pat
с начала переменной $var
. Здесь, pat
что-либо до точки, таким образом, это оставит только расширение. Эта команда, поэтому, создает каталог расширения, если это не существует.mv "$f" "${f##*.}"/
: mv
затем перемещает файл в соответствующий каталог. || mv "$f" unknown/;
: если предыдущая команда перестала работать (если этот файл/каталог), не имеет расширения, перемещают его в unknown
.Обратите внимание, что это распечатает это сообщение об ошибке, но можно безопасно проигнорировать его:
mv: cannot move ‘unknown’ to a subdirectory of itself, ‘unknown/unknown’
Если необходимо переместить только файлы, и никакие каталоги (команды выше также переместят названный каталог dir.foo
в foo/
), используйте это вместо этого:
mkdir -p unknown;
for f in *; do
[[ -f $f ]] &&
if [[ $f =~ \. ]]; then
mkdir -p "${f##*.}" &&
mv "$f" "${f##*.}"/;
else mv "$f" unknown/; fi;
done
Этот bash
сценарий сделает это: выполните его с bash script.sh <path>
или ./script.sh <path>
, где <path>
путь к папке, содержащей файлы:
#!/bin/bash
for path in ${1}/*
do
if [ -f "${path}" ]
then
extension="$(<<< "${file}" sed -rn 's/^.*\.(.*)$/\1/p')"
if [ -n "${extension}" ]
then
mkdir -p "${1}/${extension}"
mv "${path}" "${1}/${extension}"
else
mkdir -p "${1}/unknown"
mv "${path}" "${1}/unknown"
fi
fi
done
tree
вывод прежде и после выполнения сценария на tmp
каталог:
ubuntu@ubuntu:~$ tree tmp
tmp
├── a.mp4
├── a.pdf
├── a.txt
├── b.pdf
├── b.txt
├── file
├── folder
└── newfile
1 directory, 7 files
ubuntu@ubuntu:~$ bash script tmp/
ubuntu@ubuntu:~$ tree tmp
tmp
├── folder
├── mp4
│ └── a.mp4
├── pdf
│ ├── a.pdf
│ └── b.pdf
├── txt
│ ├── a.txt
│ └── b.txt
└── unknown
├── file
└── newfile
5 directories, 7 files