Cria diretórios a partir de uma lista de arquivos com espaços no nome

1

Eu tenho um diretório com uma lista de arquivos nele. Todos esses arquivos têm espaços em seus nomes.

Eu gostaria de criar um diretório, para cada arquivo, com o nome do arquivo, exceto a extensão (que é .doc para todos eles).

Por exemplo:

Meu conteúdo de diretório

first file.doc 
second file.doc 
third file.doc

Resultado esperado

first file/first file.doc 
second file/second file.doc
third file/third file.doc

Eu tenho este comando para saber o nome do diretório que tenho que criar:

find . -maxdepth 1 -name "*.doc" | awk -F ".doc" '{print $1}'

Com isso, o resultado é:

first file
second file
third file

Eu sei que preciso criar um diretório por entrada.

Eu tentei o seguinte sem sucesso:

find . -maxdepth 1 -name "*.doc" | awk -F ".doc" '{print $1}' -exec mkdir '{}' \;
#error with awk: it cannot open the file -exec because it does not exist

mkdir 'find . -maxdepth 1 -name "*.doc" | awk -F ".doc" '{print $1}''
#it creates several directories per name because there are spaces in the names

mkdir '"find . -maxdepth 1 -name "*.doc" | awk -F ".doc" '{print $1}'"'
#-bash: find . -maxdepth 1 -name *.doc | awk -F .doc '{print }': command not found

mkdir "'find . -maxdepth 1 -name "*.doc" | awk -F ".doc" '{print $1}''"
#it tries to create a unique directory with all the file names as a single name, which is not good of course

Se eu pudesse, apenas removeria todos os espaços nos nomes dos arquivos, mas preciso mantê-los para restrições de projeto: /

Quando eu puder criar esses diretórios, terei que descobrir como mover todos os arquivos em seus diretórios correspondentes. Tudo isso pode ser feito em um único comando, eu aceito:)

Estou usando o bash e o RedHat 2.6.

Obrigado pela sua ajuda. Laurent

    
por Laurent C. 03.04.2014 / 10:17

3 respostas

2

Os espaços em um nome de arquivo / diretório são bons, desde que esses nomes sejam citados corretamente:

find . -maxdepth 1 -name "*.doc" | while IFS= read -r f; do 
    mkdir -- "${f%.doc}"; 
done
    
por 03.04.2014 / 10:45
7

com zsh :

mkdir -p -- *.doc(:r)

Ou:

for f (*.doc) {
  mkdir -p -- $f:r &&
    mv -- $f $f:r/
}

O bash equivalente (embora também funcione em todos os shells do POSIX e zsh ):

for f in *.doc; do
  mkdir -p -- "${f%.*}" &&
    mv -- "$f" "${f%.*}/"
done

(observe que ele exclui arquivos ocultos).

    
por 03.04.2014 / 10:59
2
cd /path/to/dir
(   set -- *\ *
    printf 'd="%s" ; mkdir ./"${d%%.doc}"\n' "$@"
) | . /dev/stdin

Você pode definir os parâmetros de um subshell com globs de shell e depois alimentar um pipe com printf e. fonte o pipe como um script.

E se você quiser mover os arquivos em cada diretório:

cd /path/to/dir
(   set -- *\ *
    printf 'f="%s" ; d="${f%%.doc}"
        mkdir ./"$d" ; echo "mv ./\"$f\" ./\"$d\"/\"$f\""\n' "$@"
) | . /dev/stdin

Nota: Eu intencionalmente limpei o acima com eco porque eu quero que você teste a saída antes de mergulhar.

CORRIGIDO - Esqueci de usar duas% porcentagens para printf.

Eu testei isso, a propósito:

% printf 'touch ./"%s file.doc"\n' first second third fourth fifth |
    . /dev/stdin
% ls
> fifth file.doc  first file.doc  fourth file.doc  second file.doc  third file.doc

% ( set -- *\ *
    printf 'f="%s" ; d="${f%%.doc}"
    mkdir ./"$d" ; mv ./"$f" ./"$d"\n' "$@"
) | . /dev/stdin

% ls
> fifth file  first file  fourth file  second file  third file

% cd fifth\ file ; ls
> fifth file.doc
    
por 03.04.2014 / 10:25

Tags