Как циклично выполнить имена файлов в массив или выполнить пользовательский код на нем

Это - сообщение qna (Не нуждайтесь в помощи, просто требуемые для помощи другим).

Недавно работавший с некоторыми файлами и испытанными затруднениями в чтении файлов

 #version1 (error on files with spaces)
 arrFiles[0]=0
 folderLocation="/home/thenok/.local/share/recent"
 for i in $(find "$folderLocation" ! -name "*~" -type f); do
  arrFiles[0]=$[arrFiles[0]+1]   arrFiles[arrFiles[0]]="$i" 
  echo arrFiles at pos ${arrFiles[0]} found ${arrFiles[arrFiles[0]]} 
 done

найденный (хорошим) решением:

 #version2 works (ok but the global variable change bothered me)
 IFS=$'\n'       # make newlines the only separator
 arrFiles[0]=0
 folderLocation="/home/thenok/.local/share/recent"
 for i in $(find "$folderLocation" ! -name "*~" -type f); do
  arrFiles[0]=$[arrFiles[0]+1]   arrFiles[arrFiles[0]]="$i" 
  echo arrFiles at pos ${arrFiles[0]} found ${arrFiles[arrFiles[0]]} 
 done

Поскольку я не хотел изменять глобальную переменную IFS, я пытался использовать исполнительную команду в находке, но переменная модификация была тупиком (никакой код для версии 3, потерял его),

После просмотра немного я нашел, что мы можем использовать чтение для передачи по каналу:

#version4 (horrible side effect of piping is that all variables altered between do and done do not last, maybe some people will like that)
arrFileNames[0]=0 
folderLocation="/home/thenok/.local/share/recent"
find "$folderLocation" ! -name "*~" -type f | while read i; do 
 arrFileNames[++arrFileNames[0]]=${i} ;
 echo arrFiles at pos ${arrFiles[0]} found ${arrFiles[arrFiles[0]]}
done 

и управляемый, чтобы заставить его работать

#version5 works perfectly 
folderLocation="/home/thenok/.local/share/recent"
arrFileNames[0]=0 && while read i; do arrFileNames[++arrFileNames[0]]=${i} ; 
 #insert custom code
 echo arrFiles at pos ${arrFiles[0]} found ${arrFiles[arrFiles[0]]} 
 #end custom code
done < <( find "$folderLocation" ! -name "*~" -type f)

Отладка:

find "$folderLocation" ! -name "*~" -type f
#will show all files that match search location, '-type f' files not folders, '! -name "*~"' avoids backup files (usually created by office or text editors as a backup in case writing to disk failed)
#to search for a specific file name add '-name "*.pdf"' for all pdf files 
#for folder path add '-path "*/torrent/*"'
#add ! to match opposite '! -path "*/torrent/*" ! -name "*.pdf"' folder name must not contain folder called torrent and must not be a pdf
#for only current folder add ' -maxdepth 1' as first argument ie 'find  "$folderLocation" -maxdepth 1  ! -name "*~" -type f'

#for more complex conditions you can use '\(' '\)' '!' '-or' '-and'
find  "$folderLocation" -maxdepth 1  \(\( ! -name "*~" -or -path "*/torrent/*" \) -and \( -name "*~" -and ! -path "*/torrent/*" \)\) -type f'
0
задан 1 February 2016 в 02:11

2 ответа

Если бы можно быть уверены, что ни одни из имен файлов не содержат новые строки с ударом, Вы записали бы:

mapfile -t arrFiles < <(find "$folderLocation" ! -name "*~" -type f)

А колотят только путь:

shopt -s globstar nullglob extglob
arrFiles=( **/!(*~) )

, Но это будет включать каталоги. Для фильтрации их, Вы могли

arrFiles=()
for f in **/!(*~); do
    [[ -f $f ]] && arrFiles+=("$f")
done

Для исследования массива:

declare -p arrFiles
1
ответ дан 29 September 2019 в 13:10

Люди надежды находят это полезным, Q& A-стиль

Версия 5 работает лучшее, но также и работа версии 2 просто право.

0
ответ дан 29 September 2019 в 13:10

Другие вопросы по тегам:

Похожие вопросы: