3

シンボリックリンクされていないディレクトリ内のすべてのフォルダを削除し、シンボリックリンクされたフォルダとシンボリックリンクのみを保持する必要があるタスクがあります。

たとえば、3つのリソースがある場合:link、linked_folder、unlinkedfolder。linkとlinked_folderは保持されます。

現在、私はこのコードを取得することができました。これは、私たちが持っているファイルの命名構造で機能しますが、よりクリーンな解決策があるかどうか知りたいですか?

protected_folders=`ls -l | awk '/^l/ {printf $10}' | tr '/' '|'`;
symlinks=`ls -l | awk '/^l/ {print $8}' | tr "\n" "|"`;
protected_resources=$protected_folders$symlinks;
protected_resources=${protected_resources:0:${#protected_resources}-1};
folders_to_delete=`ls | grep -v -E "$protected_resources"`; 
echo $folders_to_delete | tr '\n' ' ' | tr ' ' '\000' | xargs -0 rm -rf

上記のコマンドは1行で実行できることは知っていますが、より「読みやすく」するように要求されたため、コマンドを分離しました。

どんな助けでもいただければ幸いです。

4

4 に答える 4

3

シンボリックリンクとそのターゲットを新しいディレクトリに移動してから、古いディレクトリを新しいディレクトリに置き換える方が簡単な場合があります。

警告:これは大まかなスケッチであり、アイデアを提供します。[更新:クリーンアップして、擬似コードのようにしないようにする]

# Make an empty directory to hold the symlinks and targets
# that you want to keep
DIR_TO_CLEAN=/the/directory/to/clean/up
TMP_DIR=$(mktemp -d)

for x in $DIR_TO_CLEAN/*; do
    # Move each symlink and its target to the new directory
    [[ -h $x ]] && mv $x $(readlink -f $x) $TMP_DIR
done

# FIRST!!!, confirm that $TMP_DIR has everything you want to keep,
# and $DIR_TO_CLEAN has nothing you want to keep
rm -rf $DIR_TO_CLEAN
mv $TMP_DIR $DIR_TO_CLEAN
于 2012-05-04T17:36:21.853 に答える
0

これが1つの可能な解決策です、ただ実行してください

mkdir "./onlylinkedfiles" && cd "./onlylinkedfiles"
tar -ch "../symlinks" | tar -x --strip-components=1

../symlinks/そして、あなたは現在のディレクトリ内にシンボリックリンクされたすべてのファイルとdirsだけを取得しました。

一部の自動化と同じ:

cd "delete_here"
f="../symlinkshere"; mkdir ../temporary && pushd ../temporary && tar -vch "${f}" | tar -x --strip-components=1 && rm -rf "`dirs +1`" && cd .. && mv temporary "`dirs +1`" && popd

その後、現在のディレクトリには、でシンボリックリンクを取得したファイルのみが含まれます../symlinkshere/

それを分解しましょう:

# Specify directory where symlinks are:
f="../symlinkshere"; 
# Create temporary directory:
mkdir ../temporary && 
# Remember current and change cwd to temporary folder:
pushd ../temporary && 
# Copy all symlinked files and directories to cwd:
tar -vch "${f}" | tar -x --strip-components=1 && 
# Remove directory where we been when pushd called:
rm -rf "`dirs +1`" && 
# Cd out of temporary dir:
cd .. && 
# Rename temporary to original cwd
mv temporary "`dirs +1`" && 
# Go back to path where we started:
popd

簡単に使用できるシェルスクリプトは次のとおりです。

これは現在のディレクトリで機能し、シンボリックリンクへのパスである1つの引数を取ります。
cd /path/to/clean
replacebylinks.sh /here/is/symlinks/

ファイル:~/bin/replacebylinks.sh

#!/bin/bash
tmp="`mktemp -d`"
sourced="`readlink -f ${1}`"
workd="`pwd -P`"

cd "${tmp}"
tar -vchC "${sourced}" . | tar -xv --strip-components=1

rm -vrf "${workd}"
cd ..
mv -v "${tmp}" "${workd}" && cd "${workd}"

いくつかのメモ:

  • -v出力が多すぎると思われる場合は、コマンドから 詳細スイッチを削除できます。
  • ソースディレクトリツリー全体が宛先に保持さtar -chC "source" .れない ため、使用する方がよい場合があります。-C source絶対パスでは、これは/ルートから始まります。
于 2012-05-04T16:44:48.523 に答える
0

保持したいすべてのディレクトリを次のように見つけることができます。

keep_me=$(for link in $(find . -type l); do find -L . -samefile $link; done)

これを@chepnerのソリューションと次のように組み合わせることができます。

mkdir ../new_tmp_dir
for link in $(find . -type l) 
do
    find -L . -samefile $link -print0
done | xargs -0 -I{} mv {} ../new_tmp_dir
rm -rf *
mv ../new_tmp_dir/* .

-maxdepth=1移動するディレクトリが複数レベルの深さである場合は、(を使用して)findステートメントを変更する必要がある場合があります。

于 2012-05-04T18:09:37.830 に答える
0

あなたがこれをクリーナーと呼ぶのか、エレガントなのか、それとも途方もなく複雑なのかはわかりません。セットアップはたくさんありますが、「実際の作業」の最後の数行は十分に明確です。

# map - apply a function to all arguments
map() {
  fn="$1"
  shift
  for x in "$@"; do
    $fn $x
  done
}

echoif() { if $1 "$2" ; then echo $2 ; fi }

# use map/echoif to find items that meet a criteria in a list
filter() {
  op=$1
  shift
  map "echoif $op" "$@"
}

# list grep, essentially
find_in_list() {
  item=$1
  shift
  itemis() { test $item == $1 ; }
  res=`filter itemis "$@"`
  test -n "$res"
}

not() { if $* ; then return 1; fi ; }
not_in_list() { not find_in_list $* ; }

# utility functions for filtering
islink() { test -L $1 ; }
isdir() { test -d $1 ; }

# actual work starts here
links=`filter islink *`
dests=`map readlink $links`

should_delete() { not_in_list $1 $links $dests ; }

dirs=`filter isdir *`
todelete=`filter should_delete $dirs`

# you know what to do here    
echo rm -rf $todelete
于 2012-05-04T18:46:35.907 に答える