se o arquivo é um diretório não mova mv bash

1

Estou escrevendo um script para me ajudar a manter meus arquivos organizados. Essencialmente, gostaria que o script organizasse meus arquivos com base em sua extensão. A solução atual analisa tudo em um determinado diretório. Isso é um problema porque as pastas com pontos em seus nomes são movidas.

Eu queria saber se há um if statement que pode ser usado para verificar se o diretório é um diretório real ou não. Se é realmente um diretório, o script não deve movê-lo.

Aqui está a parte do código. Eu estou usando um for loop para iterar através dos arquivos, isso é baseado praticamente fora de um script de lote antigo que eu tinha no windows, então isso pode não ser o melhor caminho a percorrer. Por favor, deixe-me saber se existe uma solução melhor:

#!/bin/bash
for i in *.*; do
  filename=$(basename -- "$i")
  extension="${filename##*.}"
  extension="$extension"files
  mkdir -p "$extension"
  mv "$i" "$extension"
done
    
por tisaconundrum 11.09.2018 / 14:04

3 respostas

2

Eu pessoalmente colocaria um loop find e while , já que você pode especificar o tipo de arquivo com -type d/f para o diretório / arquivo, respectivamente

como "um forro" do diretório em que você executará:

find . -maxdepth 1 -type f -name "*.*" | while IFS="" read -r line; do filename=$(basename -- "$line"); extension="${filename##.}.files"; mkdir -p "$extension"; mv "$line" "$extension"; done

Ou em um script:

#!/bin/bash
find . -maxdepth 1 -type f -name "*.*" |
while IFS="" read -r line; do
    filename=$(basename -- "$line")
    extension="${filename##.}.files"
    mkdir -p "$extension"
    mv "$line" "$extension"
done

explicação

find . - localiza arquivos e diretórios do diretório atual

-maxdepth 1 - apenas verifica o diretório atual (2 também verifica o próximo nível)

-type f - corresponde apenas a arquivos

-name *.* - qualquer arquivo com um "." no nome

Eu também alterei a extensão para .files em uma declaração de variável, pois presumo que seja o que você deseja. Se você quiser que tmp.txt esteja em um diretório chamado tmp.txtfiles (como em seu script atualmente), basta remover o "." assim:

extension="${filename##.}files"

EDITAR:

Então, como @Kusalananda apontou, repetir um find pode ser uma má ideia. Dito isto, você ainda pode usar find para isso, apenas usando um arquivo temporário para fazer o loop:

#!/bin/bash
find . -maxdepth 1 -type f -name "*.*" > myTemporaryFile

IFS=$'\n' # in case any filenames have spaces in them

for line in $(cat myTemporaryFile); do
    filename=$(basename -- "$line")
    extension="${filename##.}.files"
    mkdir -p "$extension"
    mv "$line" "$extension"
done

rm myTemporaryFile
    
por 11.09.2018 / 14:41
2

Vou propor dois outros métodos; um do comentário de Kusalananda e um de outro shell completamente.

Primeiro, o bash (e outros shells) tem um operador simples test para ver se algo é um diretório: [ -d something ] ; você poderia usá-lo assim:

#!/bin/bash
for i in *.*; do
  [ -d "$i" ] && continue
  # ... rest of the script
done

O item acima verificaria cada "arquivo" do curinga *.* para ver se é um diretório; se for, o teste passa e o loop continua com o próximo item (se houver).

Como alternativa, você pode usar o zsh, que possui recursos extensivos de curinga, um dos quais é limitar as correspondências a certos tipos de arquivos (arquivos regulares, diretórios, etc.). Você poderia usá-lo como:

#!/bin/zsh
for i in *.*(.)
do
  # ... rest of your script
done

A sintaxe especial de (.) é um "qualificador glob" ; os parênteses indicam que é um qualificador e o período diz que estamos procurando por arquivos simples. O resultado é que o loop for corresponderá apenas aos arquivos - nunca aos diretórios.

    
por 15.09.2018 / 02:37
1

Você pode usar -f em uma instrução if para verificar se é um arquivo:

if [ -f "${i}" ];then
  echo "${i} is a file."
else
  echo "${i} is not a file."
fi

-d pode ser usado para determinar se é um diretório e ! pode ser prefixado para inverter a lógica, ou seja, verificar se a variável não é um arquivo:

if [ ! -f "${i}" ];then
  echo "${i} is not a file"
fi
    
por 11.09.2018 / 14:06